#include <fstream>
#include <vector>
#include <deque>
-#ifdef THREADED_DNS
-#include <pthread.h>
-#endif
#include "users.h"
#include "ctables.h"
#include "globals.h"
#include "commands.h"
#include "xline.h"
#include "inspstring.h"
-#include "dnsqueue.h"
#include "helperfuncs.h"
#include "hashcomp.h"
#include "socketengine.h"
+#include "inspircd_se_config.h"
#include "userprocess.h"
#include "socket.h"
#include "typedefs.h"
InspIRCd* ServerInstance;
-int WHOWAS_STALE = 48; // default WHOWAS Entries last 2 days before they go 'stale'
-int WHOWAS_MAX = 100; // default 100 people maximum in the WHOWAS list
-
extern ModuleList modules;
extern FactoryList factory;
extern int MODCOUNT;
extern char LOG_FILE[MAXBUF];
-int openSockfd[MAX_DESCRIPTORS];
-int yield_depth;
+
int iterations = 0;
insp_sockaddr client, server;
-
socklen_t length;
extern InspSocket* socket_ref[MAX_DESCRIPTORS];
-
time_t TIME = time(NULL), OLDTIME = time(NULL);
// This table references users by file descriptor.
// its an array to make it VERY fast, as all lookups are referenced
// by an integer, meaning there is no need for a scan/search operation.
userrec* fd_ref_table[MAX_DESCRIPTORS];
-
Server* MyServer = new Server;
ServerConfig *Config = new ServerConfig;
-
user_hash clientlist;
chan_hash chanlist;
-
servernamelist servernames;
char lowermap[255];
exit (status);
}
-void Start()
+void InspIRCd::Start()
{
printf("\033[1;32mInspire Internet Relay Chat Server, compiled %s at %s\n",__DATE__,__TIME__);
printf("(C) ChatSpike Development team.\033[0m\n\n");
- printf("Developers:\t\t\033[1;32mBrain, FrostyCoolSlug, w00t, Om\033[0m\n");
+ printf("Developers:\t\t\033[1;32mBrain, FrostyCoolSlug, w00t, Om, Special\033[0m\n");
printf("Others:\t\t\t\033[1;32mSee /INFO Output\033[0m\n");
printf("Name concept:\t\t\033[1;32mLord_Zathras\033[0m\n\n");
}
FOREACH_MOD(I_OnRehash,OnRehash(""));
}
-void SetSignals()
+void InspIRCd::SetSignals()
{
signal (SIGALRM, SIG_IGN);
signal (SIGHUP, Rehash);
signal (SIGSEGV, Error);
}
-bool DaemonSeed()
+bool InspIRCd::DaemonSeed()
{
int childpid;
if ((childpid = fork ()) < 0)
return true;
}
-void WritePID(const std::string &filename)
+void InspIRCd::WritePID(const std::string &filename)
{
std::ofstream outfile(filename.c_str());
if (outfile.is_open())
InspIRCd::InspIRCd(int argc, char** argv)
{
- Start();
+ this->Start();
module_sockets.clear();
this->startup_time = time(NULL);
srand(time(NULL));
OpenLog(argv, argc);
this->stats = new serverstats();
+ this->Parser = new CommandParser();
Config->ClearStack();
Config->Read(true,NULL);
CheckRoot();
this->ModeGrok = new ModeParser();
- this->Parser = new CommandParser();
AddServerName(Config->ServerName);
CheckDie();
+ InitializeDisabledCommands(Config->DisabledCommands, this);
stats->BoundPortCount = BindPorts(true);
for(int t = 0; t < 255; t++)
memset(&Config->implement_lists,0,sizeof(Config->implement_lists));
printf("\n");
- SetSignals();
+ this->SetSignals();
if (!Config->nofork)
{
- if (!DaemonSeed())
+ if (!this->DaemonSeed())
{
printf("ERROR: could not go into daemon mode. Shutting down.\n");
Exit(ERROR);
/* Because of limitations in kqueue on freebsd, we must fork BEFORE we
* initialize the socket engine.
*/
- SE = new SocketEngine();
+ SocketEngineFactory* SEF = new SocketEngineFactory();
+ SE = SEF->Create();
+ delete SEF;
/* We must load the modules AFTER initializing the socket engine, now */
std::string InspIRCd::GetVersionString()
{
char versiondata[MAXBUF];
-#ifdef THREADED_DNS
- char dnsengine[] = "multithread";
-#else
- char dnsengine[] = "singlethread";
-#endif
+ char dnsengine[] = "singlethread-object";
if (*Config->CustomVersion)
{
snprintf(versiondata,MAXBUF,"%s %s :%s",VERSION,Config->ServerName,Config->CustomVersion);
return MODERR;
}
-void InspIRCd::erase_factory(int j)
+void InspIRCd::EraseFactory(int j)
{
int v = 0;
for (std::vector<ircd_module*>::iterator t = factory.begin(); t != factory.end(); t++)
}
}
-void InspIRCd::erase_module(int j)
+void InspIRCd::EraseModule(int j)
{
int v1 = 0;
for (std::vector<Module*>::iterator m = modules.begin(); m!= modules.end(); m++)
// found the module
log(DEBUG,"Deleting module...");
- erase_module(j);
+ this->EraseModule(j);
log(DEBUG,"Erasing module entry...");
- erase_factory(j);
+ this->EraseFactory(j);
log(DEBUG,"Removing dependent commands...");
Parser->RemoveCommands(filename);
log(DEFAULT,"Module %s unloaded",filename);
insp_sockaddr 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.
*/
}
TickMissedTimers(TIME);
expire_run = true;
- yield_depth--;
return;
}
else if ((TIME % 5) == 1)
* 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
break;
case X_ESTAB_DNS:
- /* When we are using single-threaded dns,
- * the sockets for dns end up in our mainloop.
- * When we are using multi-threaded dns,
- * each thread has its own basic poll() loop
- * within it, making them 'fire and forget'
- * and independent of the mainloop.
+ /* Handles instances of the Resolver class,
+ * a simple class extended by modules and the core for
+ * nonblocking resolving of addresses.
*/
-#ifndef THREADED_DNS
- log(DEBUG,"Type: X_ESTAB_DNS: fd=%d",activefds[activefd]);
- dns_poll(activefds[activefd]);
-#endif
+ this->Res->MarshallReads(activefds[activefd]);
break;
case X_LISTEN:
- log(DEBUG,"Type: X_LISTEN_MODULE: fd=%d",activefds[activefd]);
+ log(DEBUG,"Type: X_LISTEN: fd=%d",activefds[activefd]);
/* It's a listener */
uslen = sizeof(sock_us);
if ((incomingSockfd > -1) && (!getsockname(incomingSockfd,(sockaddr*)&sock_us,&uslen)))
{
+#ifdef IPV6
+ in_port = ntohs(sock_us.sin6_port);
+#else
in_port = ntohs(sock_us.sin_port);
+#endif
log(DEBUG,"Accepted socket %d",incomingSockfd);
/* Years and years ago, we used to resolve here
* using gethostbyaddr(). That is sucky and we
{
try
{
- Config->GetIOHook(in_port)->OnRawSocketAccept(incomingSockfd, inet_ntoa(client.sin_addr), in_port);
+#ifdef IPV6
+ Config->GetIOHook(in_port)->OnRawSocketAccept(incomingSockfd, insp_ntoa(client.sin6_addr), in_port);
+#else
+ Config->GetIOHook(in_port)->OnRawSocketAccept(incomingSockfd, insp_ntoa(client.sin_addr), in_port);
+#endif
}
catch (ModuleException& modexcept)
{
}
}
stats->statsAccept++;
+#ifdef IPV6
+ log(DEBUG,"Add ipv6 client");
+ AddClient(incomingSockfd, in_port, false, client.sin6_addr);
+#else
+ log(DEBUG,"Add ipv4 client");
AddClient(incomingSockfd, in_port, false, client.sin_addr);
- log(DEBUG,"Adding client on port %lu fd=%lu",(unsigned long)in_port,(unsigned long)incomingSockfd);
+#endif
+ log(DEBUG,"Adding client on port %d fd=%d",in_port,incomingSockfd);
}
else
{
- log(DEBUG,"Accept failed on fd %lu: %s",(unsigned long)incomingSockfd,strerror(errno));
+ log(DEBUG,"Accept failed on fd %d: %s",incomingSockfd,strerror(errno));
shutdown(incomingSockfd,2);
close(incomingSockfd);
stats->statsRefused++;
break;
}
}
- yield_depth--;
}
int InspIRCd::Run()
{
/* Until THIS point, ServerInstance == NULL */
+ this->Res = new DNS();
+
LoadAllModules(this);
/* Just in case no modules were loaded - fix for bug #101 */
/* Add the listening sockets used for client inbound connections
* to the socket engine
*/
- for (int count = 0; count < stats->BoundPortCount; count++)
- SE->AddFd(openSockfd[count],true,X_LISTEN);
+ for (unsigned long count = 0; count < stats->BoundPortCount; count++)
+ SE->AddFd(Config->openSockfd[count],true,X_LISTEN);
- WritePID(Config->PID);
+ this->WritePID(Config->PID);
/* main loop, this never returns */
expire_run = false;
- yield_depth = 0;
iterations = 0;
while (true)
int main(int argc, char** argv)
{
+ /* TEST SUITE FOR TOKENSTREAM
+ *
+ * Expected output:
+ *
+ * String: 'PRIVMSG #test FOO BAR'
+ * Token 0 = 'PRIVMSG'
+ * Token 1 = '#test'
+ * Token 2 = 'FOO'
+ * Token 3 = 'BAR'
+ * String: 'PRIVMSG #test :FOO BAR BAZ'
+ * Token 0 = 'PRIVMSG'
+ * Token 1 = '#test'
+ * Token 2 = 'FOO BAR BAZ'
+ * String: ':PRIVMSG #test :FOO BAR BAZ'
+ * Token 0 = ':PRIVMSG'
+ * String: 'AAAAAAA'
+ * Token 0 = 'AAAAAAA'
+ * String: ''
+ * NumItems = 0
+ *
+ std::string a = "PRIVMSG #test FOO BAR";
+ printf("String: '%s'\n",a.c_str());
+ irc::tokenstream test(a);
+ printf("Token 0 = '%s'\n",test.GetToken().c_str());
+ printf("Token 1 = '%s'\n",test.GetToken().c_str());
+ printf("Token 2 = '%s'\n",test.GetToken().c_str());
+ printf("Token 3 = '%s'\n",test.GetToken().c_str());
+ printf("Token 4 = '%s'\n",test.GetToken().c_str());
+
+ std::string b = "PRIVMSG #test :FOO BAR BAZ";
+ printf("String: '%s'\n",b.c_str());
+ irc::tokenstream test2(b);
+ printf("Token 0 = '%s'\n",test2.GetToken().c_str());
+ printf("Token 1 = '%s'\n",test2.GetToken().c_str());
+ printf("Token 2 = '%s'\n",test2.GetToken().c_str());
+ printf("Token 3 = '%s'\n",test2.GetToken().c_str());
+
+ std::string c = ":PRIVMSG #test :FOO BAR BAZ";
+ printf("String: '%s'\n",c.c_str());
+ irc::tokenstream test3(c);
+ printf("Token 0 = '%s'\n",test3.GetToken().c_str());
+
+ c = "AAAAAAA";
+ printf("String: '%s'\n",c.c_str());
+ irc::tokenstream test4(c);
+ printf("Token 0 = '%s'\n",test4.GetToken().c_str());
+ printf("Token 1 = '%s'\n",test4.GetToken().c_str());
+
+ c = "";
+ printf("String: '%s'\n",c.c_str());
+ irc::tokenstream test5(c);
+ printf("Token 0 = '%s'\n",test5.GetToken().c_str());
+
+ exit(0);
+ */
try
{
ServerInstance = new InspIRCd(argc, argv);