diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 178 |
1 files changed, 116 insertions, 62 deletions
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; } |