diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | src/Makefile | 4 | ||||
| -rw-r--r-- | src/config.c | 39 | ||||
| -rw-r--r-- | src/core/cs_xop.c | 19 | ||||
| -rw-r--r-- | src/core/db_plain.cpp | 2 | ||||
| -rw-r--r-- | src/core/os_shutdown.c | 3 | ||||
| -rw-r--r-- | src/core/os_stats.c | 4 | ||||
| -rw-r--r-- | src/init.c | 55 | ||||
| -rw-r--r-- | src/log.c | 4 | ||||
| -rw-r--r-- | src/main.c | 178 | ||||
| -rw-r--r-- | src/messages.c | 3 | ||||
| -rw-r--r-- | src/process.c | 11 | ||||
| -rw-r--r-- | src/protocol/bahamut.c | 2 | ||||
| -rw-r--r-- | src/protocol/inspircd11.c | 2 | ||||
| -rw-r--r-- | src/protocol/unreal32.c | 5 | ||||
| -rw-r--r-- | src/send.c | 8 | ||||
| -rw-r--r-- | src/servers.c | 9 | ||||
| -rw-r--r-- | src/sockets.cpp | 459 | ||||
| -rw-r--r-- | src/sockutil.c | 718 | ||||
| -rw-r--r-- | src/windows.cpp | 85 |
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; } @@ -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 |
