summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/Makefile4
-rw-r--r--src/config.c39
-rw-r--r--src/core/cs_xop.c19
-rw-r--r--src/core/db_plain.cpp2
-rw-r--r--src/core/os_shutdown.c3
-rw-r--r--src/core/os_stats.c4
-rw-r--r--src/init.c55
-rw-r--r--src/log.c4
-rw-r--r--src/main.c178
-rw-r--r--src/messages.c3
-rw-r--r--src/process.c11
-rw-r--r--src/protocol/bahamut.c2
-rw-r--r--src/protocol/inspircd11.c2
-rw-r--r--src/protocol/unreal32.c5
-rw-r--r--src/send.c8
-rw-r--r--src/servers.c9
-rw-r--r--src/sockets.cpp459
-rw-r--r--src/sockutil.c718
-rw-r--r--src/windows.cpp85
20 files changed, 719 insertions, 895 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a6343e8c3..4bad367b4 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -64,9 +64,9 @@ endif(MSVC)
# Generate the Anope executable and set it's linker flags, also set it to export it's symbols even though it's not a module
add_executable(${PROGRAM_NAME} ${SRC_SRCS})
set_target_properties(${PROGRAM_NAME} PROPERTIES LINKER_LANGUAGE CXX LINK_FLAGS "${LDFLAGS}" ENABLE_EXPORTS ON)
-# On Windows, also link Anope to the wsock32 library, as well as set the version
+# On Windows, also link Anope to the wsock32 and Ws2_32 library, as well as set the version
if(WIN32)
- target_link_libraries(${PROGRAM_NAME} wsock32 ${WIN32_MEMORY})
+ target_link_libraries(${PROGRAM_NAME} wsock32 Ws2_32 ${WIN32_MEMORY})
set_target_properties(${PROGRAM_NAME} PROPERTIES VERSION "${VERSION_DOTTED}")
endif(WIN32)
# Building the Anope executable requires the language files to be compiled first as well as the version.h header to be generated
diff --git a/src/Makefile b/src/Makefile
index e5a883d1b..949e7e8ec 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,7 +1,7 @@
OBJS = actions.o base64.o bots.o botserv.o channels.o chanserv.o command.o commands.o compat.o \
config.o encrypt.o hashcomp.o hostserv.o init.o ircd.o language.o log.o mail.o main.o \
memory.o memoserv.o messages.o misc.o modules.o nickserv.o operserv.o \
- process.o protocol.o send.o servers.o sessions.o slist.o sockutil.o opertype.o users.o module.o modulemanager.o configreader.o \
+ process.o protocol.o send.o servers.o sessions.o slist.o sockets.o opertype.o users.o module.o modulemanager.o configreader.o \
wildcard.o nickcore.o nickalias.o timers.o modes.o regchannel.o
INCLUDES = ../include/commands.h ../include/defs.h ../include/language.h \
@@ -71,7 +71,7 @@ send.o: send.c $(INCLUDES)
servers.o: servers.c $(INCLUDES)
sessions.o: sessions.c $(INCLUDES)
slist.o: slist.c $(INCLUDES)
-sockutil.o: sockutil.c $(INCLUDES)
+sockets.o: sockets.cpp $(INCLUDES)
opertype.o: opertype.cpp $(INCLUDES)
users.o: users.c $(INCLUDES)
vsnprintf.o: vsnprintf.c $(INCLUDES)
diff --git a/src/config.c b/src/config.c
index 70505c8c6..f023d07c2 100644
--- a/src/config.c
+++ b/src/config.c
@@ -144,7 +144,7 @@ void ServerConfig::ValidateHostname(const char *p, const std::string &tag, const
if (!strcasecmp(p, "localhost"))
return;
- int num_dots = 0;
+ int num_dots = 0, num_seps = 0;
if (*p)
{
if (*p == '.')
@@ -157,9 +157,13 @@ void ServerConfig::ValidateHostname(const char *p, const std::string &tag, const
throw ConfigException(std::string("The value of <") + tag + ":" + val + "> is not a valid hostname");
case '.':
++num_dots;
+ break;
+ case ':':
+ ++num_seps;
+ break;
}
}
- if (!num_dots)
+ if (!num_dots && !num_seps)
throw ConfigException(std::string("The value of <") + tag + ":" + val + "> is not a valid hostname");
}
}
@@ -382,8 +386,9 @@ bool DoUplink(ServerConfig *conf, const char *, const char **, ValueList &values
if (!bail)
return true;
// Validation variables
- const char *host = values[0].GetString(), *password = values[2].GetString();
- int port = values[1].GetInteger();
+ const char *host = values[0].GetString(), *password = values[3].GetString();
+ int port = values[2].GetInteger();
+ bool ipv6 = values[1].GetBool();
ValueItem vi_host(host), vi_port(port), vi_password(password);
// Validate the host to make sure it is not empty
if (!ValidateNotEmpty(conf, "uplink", "host", vi_host))
@@ -395,7 +400,7 @@ bool DoUplink(ServerConfig *conf, const char *, const char **, ValueList &values
if (!ValidateNotEmpty(conf, "uplink", "password", vi_password))
throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information.");
// If we get here, all the values are valid, we'll add it to the Uplinks list
- Config.Uplinks.push_back(new Uplink(host, port, password));
+ Config.Uplinks.push_back(new Uplink(host, port, password, ipv6));
return true;
}
@@ -597,7 +602,6 @@ int ServerConfig::Read(bool bail)
{"serverinfo", "name", "", new ValueContainerChar(&Config.ServerName), DT_HOSTNAME | DT_NORELOAD, ValidateNotEmpty},
{"serverinfo", "description", "", new ValueContainerChar(&Config.ServerDesc), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
{"serverinfo", "localhost", "", new ValueContainerChar(&Config.LocalHost), DT_HOSTNAME | DT_NORELOAD, NoValidation},
- {"serverinfo", "localport", "0", new ValueContainerUInt(&Config.LocalPort), DT_UINTEGER | DT_NORELOAD, ValidatePort},
{"serverinfo", "type", "", new ValueContainerChar(&Config.IRCDModule), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
{"serverinfo", "id", "", new ValueContainerChar(&Config.Numeric), DT_NOSPACES | DT_NORELOAD, NoValidation},
{"serverinfo", "ident", "", new ValueContainerChar(&Config.ServiceUser), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
@@ -645,6 +649,8 @@ int ServerConfig::Read(bool bail)
{"options", "enablelogchannel", "no", new ValueContainerBool(&LogChan), DT_BOOLEAN, NoValidation},
{"options", "mlock", "+nrt", new ValueContainerString(&Config.MLock), DT_STRING, NoValidation},
{"options", "botmodes", "", new ValueContainerString(&Config.BotModes), DT_STRING, NoValidation},
+ {"options", "maxretries", "10", new ValueContainerUInt(&Config.MaxRetries), DT_UINTEGER, NoValidation},
+ {"options", "retrywait", "60", new ValueContainerInt(&Config.RetryWait), DT_INTEGER, ValidateNotZero},
{"nickserv", "nick", "NickServ", new ValueContainerChar(&Config.s_NickServ), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
{"nickserv", "description", "Nickname Registration Service", new ValueContainerChar(&Config.desc_NickServ), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty},
{"nickserv", "emailregistration", "no", new ValueContainerBool(&Config.NSEmailReg), DT_BOOLEAN, NoValidation},
@@ -757,9 +763,9 @@ int ServerConfig::Read(bool bail)
* which is different to the code for reading the singular tags listed above. */
MultiConfig MultiValues[] = {
{"uplink",
- {"host", "port", "password", NULL},
- {"", "0", "", NULL},
- {DT_HOSTNAME | DT_NORELOAD, DT_UINTEGER | DT_NORELOAD, DT_NOSPACES | DT_NORELOAD},
+ {"host", "ipv6", "port", "password", NULL},
+ {"", "no", "0", "", NULL},
+ {DT_HOSTNAME | DT_NORELOAD, DT_BOOLEAN | DT_NORELOAD, DT_UINTEGER | DT_NORELOAD, DT_NOSPACES | DT_NORELOAD},
InitUplinks, DoUplink, DoneUplinks},
{"module",
{"name", NULL},
@@ -1526,21 +1532,6 @@ int read_config(int reload)
retval = Config.Read(reload ? false : true);
if (!retval) return 0; // Temporary until most of the below is modified to use the new parser -- CyberBotX
- if (!reload) {
- if (Config.LocalHost) {
- std::list<Uplink *>::iterator curr_uplink = Config.Uplinks.begin(), end_uplink = Config.Uplinks.end();
- for (; curr_uplink != end_uplink; ++curr_uplink) {
- Uplink *this_uplink = *curr_uplink;
- if (!stricmp(Config.LocalHost, this_uplink->host) && Config.LocalPort == this_uplink->port) {
- printf("\n<serverinfo:localhost> matches an <uplink:host> entry (%s)\nand <serverinfo:localport> matches an <uplink:port> entry (%d).\nThis will fail, you must make sure they are different.\n", this_uplink->host, this_uplink->port);
- retval = 0;
- }
- }
- }
- // Just in case someone put something in for <serverinfo:localport> without defining <serverinfo:localhost> too
- else Config.LocalPort = 0;
- }
-
if (temp_nsuserhost) {
if (!(s = strchr(temp_nsuserhost, '@'))) {
Config.NSEnforcerUser = temp_nsuserhost;
diff --git a/src/core/cs_xop.c b/src/core/cs_xop.c
index 2fe9daf30..fdedfa9bf 100644
--- a/src/core/cs_xop.c
+++ b/src/core/cs_xop.c
@@ -547,14 +547,11 @@ class CSXOP : public Module
if (serv_uplink && is_sync(serv_uplink))
OnUplinkSync();
- else
- {
- /* We don't want to add some commands until we are synced, so we know what modes
- * exist and what dont
- */
- ModuleManager::Attach(I_OnUplinkSync, this);
- }
- ModuleManager::Attach(I_OnChanServHelp, this);
+
+ Implementation i[] = {
+ I_OnUplinkSync, I_OnServerDisconnect, I_OnChanServHelp
+ };
+ ModuleManager::Attach(i, this, 3);
}
void OnUplinkSync()
@@ -565,6 +562,12 @@ class CSXOP : public Module
this->AddCommand(CHANSERV, new CommandCSHOP());
}
+ void OnServerDisconnect()
+ {
+ this->DelCommand(CHANSERV, "QOP");
+ this->DelCommand(CHANSERV, "HOP");
+ }
+
void OnChanServHelp(User *u)
{
if (ModeManager::FindChannelModeByName(CMODE_OWNER))
diff --git a/src/core/db_plain.cpp b/src/core/db_plain.cpp
index 02dc71b3b..fb73d2860 100644
--- a/src/core/db_plain.cpp
+++ b/src/core/db_plain.cpp
@@ -48,7 +48,7 @@ static void ReadDatabase(Module *m = NULL)
if (!db.is_open())
{
- ircdproto->SendGlobops(NULL, "Unable to open %s for reading!", DatabaseFile.c_str());
+ Alog() << "Unable to open " << DatabaseFile << " for reading!";
return;
}
diff --git a/src/core/os_shutdown.c b/src/core/os_shutdown.c
index 670b23f57..3adc2638f 100644
--- a/src/core/os_shutdown.c
+++ b/src/core/os_shutdown.c
@@ -33,8 +33,7 @@ class CommandOSShutdown : public Command
if (Config.GlobalOnCycle)
oper_global(NULL, "%s", Config.GlobalOnCycleMessage);
- save_data = 1;
- delayed_quit = 1;
+ shutting_down = 1;
return MOD_CONT;
}
diff --git a/src/core/os_stats.c b/src/core/os_stats.c
index 4ff9617ae..f159c4806 100644
--- a/src/core/os_stats.c
+++ b/src/core/os_stats.c
@@ -225,8 +225,8 @@ class CommandOSStats : public Command
{
long count, mem;
- notice_lang(Config.s_OperServ, u, OPER_STATS_BYTES_READ, total_read / 1024);
- notice_lang(Config.s_OperServ, u, OPER_STATS_BYTES_WRITTEN, total_written / 1024);
+ notice_lang(Config.s_OperServ, u, OPER_STATS_BYTES_READ, TotalRead / 1024);
+ notice_lang(Config.s_OperServ, u, OPER_STATS_BYTES_WRITTEN, TotalWritten / 1024);
get_user_stats(&count, &mem);
notice_lang(Config.s_OperServ, u, OPER_STATS_USER_MEM, count, (mem + 512) / 1024);
diff --git a/src/init.c b/src/init.c
index 5a819dcfe..e527f32c5 100644
--- a/src/init.c
+++ b/src/init.c
@@ -367,14 +367,6 @@ int init_secondary(int ac, char **av)
}
}
#else
- /* Initialize winsocks -- codemastr */
- {
- WSADATA wsa;
- if (WSAStartup(MAKEWORD(1, 1), &wsa)) {
- Alog() << "Failed to initialized WinSock library";
- return -1;
- }
- }
if (!SupportedWindowsVersion()) {
char *winver = GetWindowsVersion();
@@ -487,56 +479,23 @@ int init_secondary(int ac, char **av)
if (!bi)
{
if (Config.s_OperServ)
- bi = new BotInfo(Config.s_OperServ, Config.ServiceUser, Config.ServiceHost, Config.desc_OperServ);
+ new BotInfo(Config.s_OperServ, Config.ServiceUser, Config.ServiceHost, Config.desc_OperServ);
if (Config.s_NickServ)
- bi = new BotInfo(Config.s_NickServ, Config.ServiceUser, Config.ServiceHost, Config.desc_NickServ);
+ new BotInfo(Config.s_NickServ, Config.ServiceUser, Config.ServiceHost, Config.desc_NickServ);
if (Config.s_ChanServ)
- bi = new BotInfo(Config.s_ChanServ, Config.ServiceUser, Config.ServiceHost, Config.desc_ChanServ);
+ new BotInfo(Config.s_ChanServ, Config.ServiceUser, Config.ServiceHost, Config.desc_ChanServ);
if (Config.s_HostServ)
- bi = new BotInfo(Config.s_HostServ, Config.ServiceUser, Config.ServiceHost, Config.desc_HostServ);
+ new BotInfo(Config.s_HostServ, Config.ServiceUser, Config.ServiceHost, Config.desc_HostServ);
if (Config.s_MemoServ)
- bi = new BotInfo(Config.s_MemoServ, Config.ServiceUser, Config.ServiceHost, Config.desc_MemoServ);
+ new BotInfo(Config.s_MemoServ, Config.ServiceUser, Config.ServiceHost, Config.desc_MemoServ);
if (Config.s_BotServ)
- bi = new BotInfo(Config.s_BotServ, Config.ServiceUser, Config.ServiceHost, Config.desc_BotServ);
+ new BotInfo(Config.s_BotServ, Config.ServiceUser, Config.ServiceHost, Config.desc_BotServ);
if (Config.s_GlobalNoticer)
- bi = new BotInfo(Config.s_GlobalNoticer, Config.ServiceUser, Config.ServiceHost, Config.desc_GlobalNoticer);
+ new BotInfo(Config.s_GlobalNoticer, Config.ServiceUser, Config.ServiceHost, Config.desc_GlobalNoticer);
}
FOREACH_MOD(I_OnPostLoadDatabases, OnPostLoadDatabases());
- FOREACH_MOD(I_OnPreServerConnect, OnPreServerConnect());
-
- /* Connect to the remote server */
- std::list<Uplink *>::iterator curr_uplink = Config.Uplinks.begin(), end_uplink = Config.Uplinks.end();
- int servernum = 1;
- for (; curr_uplink != end_uplink; ++curr_uplink, ++servernum) {
- uplink_server = *curr_uplink;
- servsock = conn(uplink_server->host, uplink_server->port, Config.LocalHost, Config.LocalPort);
- if (servsock >= 0) {
- Alog() << "Connected to Server " << servernum << " (" << uplink_server->host << ":" << uplink_server->port << ")";
- break;
- }
- }
- if (curr_uplink == end_uplink) fatal_perror("Can't connect to any servers");
-
- ircdproto->SendConnect();
- FOREACH_MOD(I_OnServerConnect, OnServerConnect());
-
- sgets2(inbuf, sizeof(inbuf), servsock);
- if (strnicmp(inbuf, "ERROR", 5) == 0) {
- /* Close server socket first to stop wallops, since the other
- * server doesn't want to listen to us anyway */
- disconn(servsock);
- servsock = -1;
- fatal("Remote server returned: %s", inbuf);
- }
-
- /* Announce a logfile error if there was one */
- if (openlog_failed) {
- ircdproto->SendGlobops(NULL, "Warning: couldn't open logfile: %s",
- strerror(openlog_errno));
- }
- /* Success! */
return 0;
}
diff --git a/src/log.c b/src/log.c
index a0cb38d59..41472e7ad 100644
--- a/src/log.c
+++ b/src/log.c
@@ -207,7 +207,7 @@ void fatal(const char *fmt, ...)
fprintf(logfile, "%s FATAL: %s\n", buf, buf2);
if (nofork)
fprintf(stderr, "%s FATAL: %s\n", buf, buf2);
- if (servsock >= 0)
+ if (UplinkSock)
ircdproto->SendGlobops(NULL, "FATAL ERROR! %s", buf2);
/* one of the many places this needs to be called from */
@@ -245,7 +245,7 @@ void fatal_perror(const char *fmt, ...)
if (nofork)
fprintf(stderr, "%s FATAL: %s: %s\n", buf, buf2,
strerror(errno_save));
- if (servsock >= 0)
+ if (UplinkSock)
ircdproto->SendGlobops(NULL, "FATAL ERROR! %s: %s", buf2,
strerror(errno_save));
diff --git a/src/main.c b/src/main.c
index 28f1fd51d..7288e832d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -64,17 +64,11 @@ std::string binary_dir; /* Used to store base path for Anope */
int quitting = 0;
/* Set to 1 if we are to quit after saving databases */
-int delayed_quit = 0;
+int shutting_down = 0;
/* Contains a message as to why services is terminating */
const char *quitmsg = NULL;
-/* Input buffer - global, so we can dump it if something goes wrong */
-char inbuf[BUFSIZE];
-
-/* Socket for talking to server */
-int servsock = -1;
-
/* Should we update the databases now? */
int save_data = 0;
@@ -123,6 +117,28 @@ class UpdateTimer : public Timer
}
};
+Socket *UplinkSock = NULL;
+
+class UplinkSocket : public Socket
+{
+ public:
+ UplinkSocket(const std::string &nTargetHost, int nPort, const std::string &nBindHost = "", bool nIPv6 = false) : Socket(nTargetHost, nPort, nBindHost, nIPv6)
+ {
+ UplinkSock = this;
+ }
+
+ ~UplinkSocket()
+ {
+ UplinkSock = NULL;
+ }
+
+ bool Read(const std::string &buf)
+ {
+ process(buf);
+ return true;
+ }
+};
+
/*************************************************************************/
/* Run expiration routines */
@@ -160,6 +176,9 @@ extern void expire_all()
void save_databases()
{
+ if (readonly)
+ return;
+
EventReturn MOD_RESULT;
FOREACH_RESULT(I_OnSaveDatabase, OnSaveDatabase());
Alog(LOG_DEBUG) << "Saving FFF databases";
@@ -181,7 +200,7 @@ void do_restart_services()
if (!quitmsg)
quitmsg = "Restarting";
ircdproto->SendSquit(Config.ServerName, quitmsg);
- disconn(servsock);
+ delete UplinkSock;
close_log();
/* First don't unload protocol module, then do so */
modules_unload_all(false);
@@ -223,8 +242,8 @@ static void services_shutdown()
u = next;
}
}
+ delete UplinkSock;
FOREACH_MOD(I_OnShutdown, OnShutdown());
- disconn(servsock);
/* First don't unload protocol module, then do so */
modules_unload_all(false);
modules_unload_all(true);
@@ -366,6 +385,34 @@ std::string GetFullProgDir(char *argv0)
/*************************************************************************/
+static bool Connect()
+{
+ /* Connect to the remote server */
+ std::list<Uplink *>::iterator curr_uplink = Config.Uplinks.begin(), end_uplink = Config.Uplinks.end();
+ int servernum = 1;
+ for (; curr_uplink != end_uplink; ++curr_uplink, ++servernum)
+ {
+ uplink_server = *curr_uplink;
+
+ try
+ {
+ new UplinkSocket(uplink_server->host, uplink_server->port, Config.LocalHost ? Config.LocalHost : "", uplink_server->ipv6);
+ }
+ catch (SocketException& ex)
+ {
+ Alog() << "Unable to connect to server" << servernum << " (" << uplink_server->host << ":" << uplink_server->port << "), " << ex.GetReason();
+ continue;
+ }
+
+ Alog() << "Connected to Server " << servernum << " (" << uplink_server->host << ":" << uplink_server->port << ")";
+ return true;
+ }
+
+ return false;
+}
+
+/*************************************************************************/
+
/* Main routine. (What does it look like? :-) ) */
int main(int ac, char **av, char **envp)
@@ -423,9 +470,14 @@ int main(int ac, char **av, char **envp)
if ((i = init_secondary(ac, av)) != 0)
return i;
+ FOREACH_MOD(I_OnPreServerConnect, OnPreServerConnect());
+
+ /* If the first connect fails give up, don't sit endlessly trying to reconnect */
+ if (!Connect())
+ fatal_perror("Can't connect to any servers");
- /* We have a line left over from earlier, so process it first. */
- process();
+ ircdproto->SendConnect();
+ FOREACH_MOD(I_OnServerConnect, OnServerConnect());
started = 1;
@@ -456,69 +508,71 @@ int main(int ac, char **av, char **envp)
/*** Main loop. ***/
while (!quitting)
{
- time_t t = time(NULL);
+ while (!quitting && UplinkSock)
+ {
+ time_t t = time(NULL);
- Alog(LOG_DEBUG_2) << "Top of main loop";
+ Alog(LOG_DEBUG_2) << "Top of main loop";
- if (!readonly && save_data)
- {
- if (!noexpire)
- expire_all();
- if (delayed_quit)
- ircdproto->SendGlobops(NULL, "Updating databases on shutdown, please wait.");
- save_databases();
- if (save_data < 0)
+ if (!readonly && (save_data || shutting_down))
+ {
+ if (!noexpire)
+ expire_all();
+ if (shutting_down)
+ ircdproto->SendGlobops(NULL, "Updating databases on shutdown, please wait.");
+ save_databases();
+ save_data = 0;
+ }
+
+ if (shutting_down)
+ {
+ quitting = 1;
break;
- save_data = 0;
- }
+ }
- if (delayed_quit)
- break;
+ if (t - last_check >= Config.TimeoutCheck)
+ {
+ TimerManager::TickTimers(t);
+ last_check = t;
+ }
- if (t - last_check >= Config.TimeoutCheck)
+ /* Process any modes that need to be (un)set */
+ ModeManager::ProcessModes();
+
+ /* Process the socket engine */
+ socketEngine.Process();
+ }
+
+ if (quitting)
{
- TimerManager::TickTimers(t);
- last_check = t;
+ /* Disconnect and exit */
+ services_shutdown();
}
+ else
+ {
+ FOREACH_MOD(I_OnServerDisconnect, OnServerDisconnect());
- /* Process any modes that need to be (un)set */
- ModeManager::ProcessModes();
-
- /* this is a nasty nasty typecast. we need to rewrite the
- socket stuff -Certus */
- i = static_cast<int>(reinterpret_cast<long>(sgets2(inbuf, sizeof(inbuf), servsock)));
- if ((i > 0) || (i < (-1))) {
- process();
- } else if (i == 0) {
- int errno_save = errno;
- quitmsg = new char[BUFSIZE];
- if (quitmsg) {
- // Naughty, but oh well. :)
- snprintf(const_cast<char *>(quitmsg), BUFSIZE,
- "Read error from server: %s (error num: %d)",
- strerror(errno_save), errno_save);
- } else {
- quitmsg = "Read error from server";
+ unsigned j = 0;
+ for (; j < (Config.MaxRetries ? Config.MaxRetries : j + 1); ++j)
+ {
+ Alog() << "Disconnected from the server, retrying in " << Config.RetryWait << " seconds";
+
+ sleep(Config.RetryWait);
+ if (Connect())
+ {
+ ircdproto->SendConnect();
+ FOREACH_MOD(I_OnServerConnect, OnServerConnect());
+ break;
+ }
+ }
+ if (Config.MaxRetries && j == Config.MaxRetries)
+ {
+ Alog() << "Max connection retry limit exceeded";
+ quitting = 1;
}
- quitting = 1;
-
- /* Save the databases */
- if (!readonly)
- save_databases();
}
}
-
- /* Check for restart instead of exit */
- if (save_data == -2)
- {
- do_restart_services();
- return 0;
- }
-
- /* Disconnect and exit */
- services_shutdown();
-
return 0;
}
diff --git a/src/messages.c b/src/messages.c
index fe8f46542..31ba669eb 100644
--- a/src/messages.c
+++ b/src/messages.c
@@ -231,8 +231,7 @@ int m_stats(const char *source, int ac, const char **av)
if (u && is_oper(u)) {
ircdproto->SendNumeric(Config.ServerName, 211, source, "Server SendBuf SentBytes SentMsgs RecvBuf RecvBytes RecvMsgs ConnTime");
- ircdproto->SendNumeric(Config.ServerName, 211, source, "%s %d %d %d %d %d %d %ld", uplink_server->host, write_buffer_len(), total_written, -1, read_buffer_len(),
- total_read, -1, time(NULL) - start_time);
+ ircdproto->SendNumeric(Config.ServerName, 211, source, "%s %d %d %d %d %d %d %ld", uplink_server->host, UplinkSock->WriteBufferLen(), TotalWritten, -1, UplinkSock->ReadBufferLen(), TotalRead, -1, time(NULL) - start_time);
}
ircdproto->SendNumeric(Config.ServerName, 219, source, "%c :End of /STATS report.", *av[0] ? *av[0] : '*');
diff --git a/src/process.c b/src/process.c
index 2c85e1644..b593b0d88 100644
--- a/src/process.c
+++ b/src/process.c
@@ -281,7 +281,7 @@ int split_buf(char *buf, const char ***argv, int colon_special)
/* process: Main processing routine. Takes the string in inbuf (global
* variable) and does something appropriate with it. */
-void process()
+void process(const std::string &buffer)
{
int retVal = 0;
Message *current = NULL;
@@ -299,11 +299,11 @@ void process()
*cmd = '\0';
/* If debugging, log the buffer */
- Alog(LOG_DEBUG) << "Received: " << inbuf;
+ Alog(LOG_DEBUG) << "Received: " << buffer;
/* First make a copy of the buffer so we have the original in case we
* crash - in that case, we want to know what we crashed on. */
- strscpy(buf, inbuf, sizeof(buf));
+ strscpy(buf, buffer.c_str(), sizeof(buf));
doCleanBuffer(buf);
@@ -359,9 +359,8 @@ void process()
}
}
}
- } else {
- Alog(LOG_DEBUG) << "unknown message from server (" << inbuf << ")";
- }
+ } else
+ Alog(LOG_DEBUG) << "unknown message from server (" << buffer << ")";
/* Free argument list we created */
free(av);
diff --git a/src/protocol/bahamut.c b/src/protocol/bahamut.c
index 34886126c..6bab9ff2c 100644
--- a/src/protocol/bahamut.c
+++ b/src/protocol/bahamut.c
@@ -283,7 +283,7 @@ class BahamutIRCdProto : public IRCDProto
{
bahamut_cmd_pass(uplink_server->password);
bahamut_cmd_capab();
- me_server = new_server(NULL, Config.ServerName, Config.ServerDesc, SERVER_ISME, NULL);
+ me_server = new_server(NULL, Config.ServerName, Config.ServerDesc, SERVER_ISME, "");
SendServer(me_server);
bahamut_cmd_svinfo();
bahamut_cmd_burst();
diff --git a/src/protocol/inspircd11.c b/src/protocol/inspircd11.c
index 1357f1e46..f193d685c 100644
--- a/src/protocol/inspircd11.c
+++ b/src/protocol/inspircd11.c
@@ -251,7 +251,7 @@ class InspIRCdProto : public IRCDProto
void SendConnect()
{
inspircd_cmd_pass(uplink_server->password);
- me_server = new_server(NULL, Config.ServerName, Config.ServerDesc, SERVER_ISME, NULL);
+ me_server = new_server(NULL, Config.ServerName, Config.ServerDesc, SERVER_ISME, "");
SendServer(me_server);
send_cmd(NULL, "BURST");
send_cmd(Config.ServerName, "VERSION :Anope-%s %s :%s - %s (%s) -- %s", version_number, Config.ServerName, ircd->name, version_flags, Config.EncModuleList.begin()->c_str(), version_build);
diff --git a/src/protocol/unreal32.c b/src/protocol/unreal32.c
index 1ecd12860..c44293ed8 100644
--- a/src/protocol/unreal32.c
+++ b/src/protocol/unreal32.c
@@ -291,10 +291,7 @@ class UnrealIRCdProto : public IRCDProto
{
unreal_cmd_capab();
unreal_cmd_pass(uplink_server->password);
- if (Config.Numeric)
- me_server = new_server(NULL, Config.ServerName, Config.ServerDesc, SERVER_ISME, Config.Numeric);
- else
- me_server = new_server(NULL, Config.ServerName, Config.ServerDesc, SERVER_ISME, NULL);
+ me_server = new_server(NULL, Config.ServerName, Config.ServerDesc, SERVER_ISME, (Config.Numeric ? Config.Numeric : ""));
SendServer(me_server);
}
diff --git a/src/send.c b/src/send.c
index a032b1f03..360d981f3 100644
--- a/src/send.c
+++ b/src/send.c
@@ -35,12 +35,12 @@ void send_cmd(const char *source, const char *fmt, ...)
if (source)
{
- sockprintf(servsock, ":%s %s\r\n", source, buf);
+ UplinkSock->Write(":%s %s", source, buf);
Alog(LOG_DEBUG) << "Sent: :" << source << " " << buf;
}
else
{
- sockprintf(servsock, "%s\r\n", buf);
+ UplinkSock->Write("%s", buf);
Alog(LOG_DEBUG) << "Sent: "<< buf;
}
@@ -62,12 +62,12 @@ void send_cmd(const std::string &source, const char *fmt, ...)
if (!source.empty())
{
- sockprintf(servsock, ":%s %s\r\n", source.c_str(), buf);
+ UplinkSock->Write(":%s %s", source.c_str(), buf);
Alog(LOG_DEBUG) << "Sent: :" << source << " " << buf;
}
else
{
- sockprintf(servsock, "%s\r\n", buf);
+ UplinkSock->Write("%s", buf);
Alog(LOG_DEBUG) << "Sent: " << buf;
}
diff --git a/src/servers.c b/src/servers.c
index c16305c1d..b9ea91171 100644
--- a/src/servers.c
+++ b/src/servers.c
@@ -118,7 +118,7 @@ Server *next_server(ServerFlag flag)
* @return Server Struct
*/
Server *new_server(Server * server_uplink, const char *name, const char *desc,
- ServerFlag flag, const char *suid)
+ ServerFlag flag, const std::string &suid)
{
Server *serv;
@@ -131,11 +131,10 @@ Server *new_server(Server * server_uplink, const char *name, const char *desc,
if (flag != SERVER_START)
serv->SetFlag(flag);
serv->uplink = server_uplink;
- if (suid) {
- serv->suid = sstrdup(suid);
- } else {
+ if (!suid.empty())
+ serv->suid = sstrdup(suid.c_str());
+ else
serv->suid = NULL;
- }
serv->sync = SSYNC_IN_PROGRESS;
serv->links = NULL;
diff --git a/src/sockets.cpp b/src/sockets.cpp
new file mode 100644
index 000000000..58370b4f8
--- /dev/null
+++ b/src/sockets.cpp
@@ -0,0 +1,459 @@
+#include "services.h"
+
+SocketEngine socketEngine;
+int32 TotalRead = 0;
+int32 TotalWritten = 0;
+
+/** Trims all the \r and \ns from the begining and end of a string
+ * @return A string without trailing \r and \ns
+ */
+static void TrimBuf(std::string &buffer)
+{
+ while (!buffer.empty() && (buffer[0] == '\r' || buffer[0] == '\n'))
+ buffer.erase(buffer.begin());
+ while (!buffer.empty() && (buffer[buffer.length() - 1] == '\r' || buffer[buffer.length() - 1] == '\n'))
+ buffer.erase(buffer.length() - 1);
+}
+
+/** Default constructor
+ * @param nTargetHost Hostname to connect to
+ * @param nPort Port to connect to
+ * @param nBindHos Host to bind to when connecting
+ * @param nIPv6 true to use IPv6
+ */
+Socket::Socket(const std::string &nTargetHost, int nPort, const std::string &nBindHost, bool nIPv6) : TargetHost(nTargetHost), Port(nPort), BindHost(nBindHost), IPv6(nIPv6)
+{
+ if (!IPv6 && (TargetHost.find(':') != std::string::npos || BindHost.find(':') != std::string::npos))
+ IPv6 = true;
+
+ Sock = socket(IPv6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0);
+
+ addrinfo hints;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = 0;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_family = IPv6 ? AF_INET6 : AF_INET;
+
+ if (!BindHost.empty())
+ {
+ addrinfo *bindar;
+ sockaddr_in bindaddr;
+ sockaddr_in6 bindaddr6;
+
+ int Bound = -1;
+ if (getaddrinfo(BindHost.c_str(), NULL, &hints, &bindar) == 0)
+ {
+ if (IPv6)
+ memcpy(&bindaddr6, bindar->ai_addr, bindar->ai_addrlen);
+ else
+ memcpy(&bindaddr, bindar->ai_addr, bindar->ai_addrlen);
+
+ freeaddrinfo(bindar);
+
+ Bound = bind(Sock, reinterpret_cast<sockaddr *>(&bindaddr), sizeof(bindaddr));
+ }
+ if (!Bound)
+ {
+ if (IPv6)
+ {
+ bindaddr6.sin6_family = AF_INET6;
+
+ if (inet_pton(AF_INET6, BindHost.c_str(), &bindaddr6.sin6_addr) < 1)
+ {
+ throw SocketException("Invalid bind host");
+ }
+
+ if (bind(Sock, reinterpret_cast<sockaddr *>(&bindaddr6), sizeof(bindaddr6)) == -1)
+ {
+ throw SocketException("Unable to bind to address");
+ }
+ }
+ else
+ {
+ bindaddr.sin_family = AF_INET;
+
+ if (inet_pton(bindaddr.sin_family, BindHost.c_str(), &bindaddr.sin_addr) < 1)
+ {
+ throw SocketException("Invalid bind host");
+ }
+
+ if (bind(Sock, reinterpret_cast<sockaddr *>(&bindaddr), sizeof(bindaddr)) == -1)
+ {
+ throw SocketException("Unable to bind to address");
+ }
+ }
+ }
+ }
+
+ addrinfo *conar;
+ sockaddr_in conaddr;
+ sockaddr_in6 conaddr6;
+ if (getaddrinfo(TargetHost.c_str(), NULL, &hints, &conar) == 0)
+ {
+ if (IPv6)
+ memcpy(&conaddr6, conar->ai_addr, conar->ai_addrlen);
+ else
+ memcpy(&conaddr, conar->ai_addr, conar->ai_addrlen);
+
+ freeaddrinfo(conar);
+ }
+ else
+ {
+ if (IPv6)
+ {
+ if (inet_pton(AF_INET6, TargetHost.c_str(), &conaddr6.sin6_addr) < 1)
+ {
+ throw SocketException("Invalid server address");
+ }
+ }
+ else
+ {
+ if (inet_pton(AF_INET, TargetHost.c_str(), &conaddr.sin_addr) < 1)
+ {
+ throw SocketException("Invalid server address");
+ }
+ }
+ }
+
+ if (IPv6)
+ {
+ conaddr6.sin6_family = AF_INET6;
+ conaddr6.sin6_port = htons(Port);
+
+ if (connect(Sock, reinterpret_cast<sockaddr *>(&conaddr6), sizeof(conaddr6)) < 0)
+ {
+ throw SocketException("Error connecting to server");
+ }
+ }
+ else
+ {
+ conaddr.sin_family = AF_INET;
+ conaddr.sin_port = htons(Port);
+
+ if (connect(Sock, reinterpret_cast<sockaddr *>(&conaddr), sizeof(con