mirror of
https://github.com/matrix-construct/construct
synced 2025-01-13 08:23:56 +01:00
ircd: Introduce ASIO; stub for signal handling and console UI.
This commit is contained in:
parent
baa60ed253
commit
5aeeb73e20
8 changed files with 379 additions and 523 deletions
|
@ -20,15 +20,18 @@
|
|||
*/
|
||||
|
||||
#include <ircd/ircd.h>
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
using namespace ircd;
|
||||
namespace path = ircd::path;
|
||||
using ircd::lgetopt;
|
||||
|
||||
bool printversion;
|
||||
bool testing_conf;
|
||||
lgetopt opts[] =
|
||||
{
|
||||
{ "help", NULL, lgetopt::USAGE, "Print this text" },
|
||||
{ "version", &printversion, lgetopt::BOOL, "Print version and exit" },
|
||||
{ "configfile", &ConfigFileEntry.configfile, lgetopt::STRING, "File to use for ircd.conf" },
|
||||
{ "configfile", &ircd::ConfigFileEntry.configfile, lgetopt::STRING, "File to use for ircd.conf" },
|
||||
{ "conftest", &testing_conf, lgetopt::YESNO, "Test the configuration files and exit" },
|
||||
{ "debug", &ircd::debugmode, lgetopt::BOOL, "Enable options for debugging" },
|
||||
{ NULL, NULL, lgetopt::STRING, NULL },
|
||||
|
@ -51,17 +54,22 @@ const char *const usererrstr
|
|||
%s
|
||||
)"};
|
||||
|
||||
static void print_version();
|
||||
static void handle_interruption();
|
||||
static void sigfd_handler(const boost::system::error_code &, int);
|
||||
static bool startup_checks();
|
||||
static void print_version();
|
||||
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::signal_set sigs(ios);
|
||||
|
||||
int main(int argc, char *const *argv)
|
||||
try
|
||||
{
|
||||
umask(077); // better safe than sorry --SRB
|
||||
|
||||
ConfigFileEntry.dpath = path::get(path::PREFIX);
|
||||
ConfigFileEntry.configfile = path::get(path::IRCD_CONF); // Server configuration file
|
||||
ConfigFileEntry.connect_timeout = 30; // Default to 30
|
||||
ircd::ConfigFileEntry.dpath = path::get(path::PREFIX);
|
||||
ircd::ConfigFileEntry.configfile = path::get(path::IRCD_CONF); // Server configuration file
|
||||
ircd::ConfigFileEntry.connect_timeout = 30; // Default to 30
|
||||
|
||||
parseargs(&argc, &argv, opts);
|
||||
if(!startup_checks())
|
||||
|
@ -73,21 +81,34 @@ try
|
|||
return 0;
|
||||
}
|
||||
|
||||
return ircd::run();
|
||||
sigs.add(SIGINT);
|
||||
sigs.add(SIGQUIT);
|
||||
sigs.async_wait(sigfd_handler);
|
||||
ircd::init(ios);
|
||||
ios.run(); // Blocks until a clean exit or an exception comes out of it.
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
if(ircd::debugmode)
|
||||
throw;
|
||||
|
||||
/*
|
||||
* Why EXIT_FAILURE here?
|
||||
* Because if ircd_die_cb() is called it's because of a fatal
|
||||
* error inside libcharybdis, and we don't know how to handle the
|
||||
* exception, so it is logical to return a FAILURE exit code here.
|
||||
* --nenolod
|
||||
*
|
||||
* left the comment but the code is gone -jzk
|
||||
*/
|
||||
fprintf(stderr, fatalerrstr, e.what());
|
||||
return 1;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
void print_version()
|
||||
{
|
||||
printf("VERSION :%s\n",
|
||||
info::version.c_str());
|
||||
ircd::info::version.c_str());
|
||||
|
||||
#ifdef CUSTOM_BRANDING
|
||||
printf("VERSION :based on %s-%s\n",
|
||||
|
@ -103,10 +124,10 @@ try
|
|||
{
|
||||
#ifndef _WIN32
|
||||
if(geteuid() == 0)
|
||||
throw error("Don't run ircd as root!!!");
|
||||
throw ircd::error("Don't run ircd as root!!!");
|
||||
#endif
|
||||
|
||||
path::chdir(ConfigFileEntry.dpath);
|
||||
path::chdir(ircd::ConfigFileEntry.dpath);
|
||||
return true;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
|
@ -114,3 +135,78 @@ catch(const std::exception &e)
|
|||
fprintf(stderr, usererrstr, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
sigfd_handler(const boost::system::error_code &ec,
|
||||
int signum)
|
||||
{
|
||||
switch(ec.value())
|
||||
{
|
||||
using namespace boost::system::errc;
|
||||
|
||||
case success: break;
|
||||
case operation_canceled: return;
|
||||
default: throw std::runtime_error(ec.message());
|
||||
}
|
||||
|
||||
switch(signum)
|
||||
{
|
||||
case SIGINT:
|
||||
handle_interruption();
|
||||
break;
|
||||
|
||||
case SIGQUIT:
|
||||
printf("\nQUIT\n");
|
||||
ios.stop();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
sigs.async_wait(sigfd_handler);
|
||||
}
|
||||
|
||||
const char *const interruption_message
|
||||
{R"(
|
||||
*** Charybdis is now paused. A command line has been presented below.
|
||||
*** This is actually an IRC client and your commands will originate from
|
||||
*** the server itself. The server will resume when you hit enter.
|
||||
***
|
||||
*** - To exit cleanly, type DIE
|
||||
*** - To exit quickly, type ctrl-\ [SIGQUIT]
|
||||
*** - To exit immediately, type EXIT
|
||||
*** - To generate a coredump for developers, type ABORT
|
||||
***
|
||||
*** This message will be skipped on the next interrupt.
|
||||
)"};
|
||||
|
||||
void
|
||||
handle_interruption()
|
||||
{
|
||||
static bool seen_the_message;
|
||||
if(!seen_the_message)
|
||||
{
|
||||
seen_the_message = true;
|
||||
std::cout << interruption_message;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
std::cout << "\n> " << std::flush;
|
||||
std::getline(std::cin, line);
|
||||
if(std::cin.eof())
|
||||
{
|
||||
std::cout << std::endl;
|
||||
std::cin.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if(line.empty())
|
||||
return;
|
||||
|
||||
if(line == "ABORT")
|
||||
abort();
|
||||
|
||||
if(line == "EXIT")
|
||||
exit(0);
|
||||
}
|
||||
|
|
|
@ -850,14 +850,14 @@ if [[ "$boost_linkage" = "shared" ]]; then
|
|||
[
|
||||
AC_SUBST(BOOST_LIBS, ["-lboost_filesystem-mgw53-1_61.dll -lboost_system-mgw53-1_61.dll"])
|
||||
], [
|
||||
AC_SUBST(BOOST_LIBS, ["-lboost_filesystem -lboost_system"])
|
||||
AC_SUBST(BOOST_LIBS, ["-lboost_filesystem -lboost_system -lpthread"])
|
||||
])
|
||||
else
|
||||
AM_COND_IF([MINGW],
|
||||
[
|
||||
AC_SUBST(BOOST_LIBS, ["$boost_libdir/libboost_filesystem-mgw53-1_61.dll.a $boost_libdir/libboost_system-mgw53-1_61.dll.a"])
|
||||
], [
|
||||
AC_SUBST(BOOST_LIBS, ["-lboost_filesystem -lboost_system"])
|
||||
AC_SUBST(BOOST_LIBS, ["-lboost_filesystem -lboost_system -lpthread"])
|
||||
dnl AC_SUBST(BOOST_LIBS, ["$boost_libdir/libboost_filesystem.a"])
|
||||
dnl AC_SUBST(BOOST_LIBS, ["$boost_libdir/libboost_system.a"])
|
||||
])
|
||||
|
|
|
@ -32,9 +32,19 @@
|
|||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
// Allow a reference to an ios to be passed to ircd
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
|
||||
struct io_service;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ircd {
|
||||
|
||||
extern bool debugmode;
|
||||
extern boost::asio::io_service *ios;
|
||||
|
||||
struct SetOptions
|
||||
{
|
||||
|
@ -100,12 +110,10 @@ extern bool ircd_zlib_ok;
|
|||
extern int maxconnections;
|
||||
|
||||
void restart(const char *) __attribute__((noreturn));
|
||||
void ircd_shutdown() __attribute__((noreturn));
|
||||
void server_reboot(void) __attribute__((noreturn));
|
||||
|
||||
void setup_signals();
|
||||
void ircd_shutdown(const char *reason) __attribute__((noreturn));
|
||||
|
||||
int run();
|
||||
void init(boost::asio::io_service &ios);
|
||||
|
||||
} // namespace ircd
|
||||
#endif // __cplusplus
|
||||
|
|
|
@ -58,7 +58,6 @@ libircd_la_SOURCES = \
|
|||
ircd.cc \
|
||||
ircd_lexer.cc \
|
||||
ircd_parser.cc \
|
||||
ircd_signal.cc \
|
||||
listener.cc \
|
||||
logger.cc \
|
||||
match.cc \
|
||||
|
|
539
ircd/ircd.cc
539
ircd/ircd.cc
|
@ -23,14 +23,10 @@
|
|||
* USA
|
||||
*/
|
||||
|
||||
bool ircd::debugmode;
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
namespace ircd {
|
||||
|
||||
static void
|
||||
ircd_die_cb(const char *str) __attribute__((noreturn));
|
||||
|
||||
/* /quote set variables */
|
||||
struct SetOptions GlobalSetOptions;
|
||||
|
||||
|
@ -44,6 +40,8 @@ struct admin_info AdminInfo;
|
|||
struct Counter Count;
|
||||
struct ServerStatistics ServerStats;
|
||||
|
||||
struct ev_entry *check_splitmode_ev;
|
||||
|
||||
int maxconnections;
|
||||
client::client me; /* That's me */
|
||||
struct LocalUser meLocalUser; /* That's also part of me */
|
||||
|
@ -79,73 +77,6 @@ int split_users;
|
|||
int split_servers;
|
||||
int eob_count;
|
||||
|
||||
void
|
||||
ircd_shutdown(const char *reason)
|
||||
{
|
||||
client::client *target_p;
|
||||
rb_dlink_node *ptr;
|
||||
|
||||
RB_DLINK_FOREACH(ptr, lclient_list.head)
|
||||
{
|
||||
target_p = (client::client *)ptr->data;
|
||||
|
||||
sendto_one(target_p, ":%s NOTICE %s :Server Terminating. %s",
|
||||
me.name, target_p->name, reason);
|
||||
}
|
||||
|
||||
RB_DLINK_FOREACH(ptr, serv_list.head)
|
||||
{
|
||||
target_p = (client::client *)ptr->data;
|
||||
|
||||
sendto_one(target_p, ":%s ERROR :Terminated by %s",
|
||||
me.name, reason);
|
||||
}
|
||||
|
||||
log::critical("Server Terminating. %s", reason);
|
||||
log::close();
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* print_startup - print startup information
|
||||
*/
|
||||
static void
|
||||
print_startup(const pid_t &pid)
|
||||
{
|
||||
log::notice("Server started @ %s pid[%d]",
|
||||
ConfigFileEntry.dpath,
|
||||
pid);
|
||||
}
|
||||
|
||||
/*
|
||||
* init_sys
|
||||
*
|
||||
* inputs - boot_daemon flag
|
||||
* output - none
|
||||
* side effects - if boot_daemon flag is not set, don't daemonize
|
||||
*/
|
||||
static void
|
||||
init_sys(void)
|
||||
{
|
||||
#if !defined(_WIN32) && defined(RLIMIT_NOFILE) && defined(HAVE_SYS_RESOURCE_H)
|
||||
struct rlimit limit;
|
||||
|
||||
if(!getrlimit(RLIMIT_NOFILE, &limit))
|
||||
{
|
||||
maxconnections = limit.rlim_cur;
|
||||
if(maxconnections <= MAX_BUFFER)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Shell FD limits are too low.\n");
|
||||
fprintf(stderr, "ERROR: charybdis reserves %d FDs, shell limits must be above this\n", MAX_BUFFER);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif /* RLIMIT_FD_MAX */
|
||||
maxconnections = MAXCONNECTIONS;
|
||||
}
|
||||
|
||||
static void
|
||||
check_rehash(void *unused)
|
||||
{
|
||||
|
@ -220,84 +151,182 @@ initialize_global_set_options(void)
|
|||
/* memset( &ConfigChannel, 0, sizeof(ConfigChannel)); */
|
||||
|
||||
/* End of global set options */
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* initialize_server_capabs
|
||||
*
|
||||
* inputs - none
|
||||
* output - none
|
||||
*/
|
||||
static void
|
||||
initialize_server_capabs(void)
|
||||
{
|
||||
default_server_capabs &= ~CAP_ZIP;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* setup_corefile
|
||||
*
|
||||
* inputs - nothing
|
||||
* output - nothing
|
||||
* side effects - setups corefile to system limits.
|
||||
* -kre
|
||||
*/
|
||||
static void
|
||||
setup_corefile(void)
|
||||
{
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
struct rlimit rlim; /* resource limits */
|
||||
bool debugmode;
|
||||
boost::asio::io_service *ios;
|
||||
|
||||
/* Set corefilesize to maximum */
|
||||
if(!getrlimit(RLIMIT_CORE, &rlim))
|
||||
static void sigfd_handler(const boost::system::error_code &, int);
|
||||
std::unique_ptr<boost::asio::signal_set> sigfd;
|
||||
|
||||
static void seed_random();
|
||||
static void init_sigs();
|
||||
static void init_sys();
|
||||
|
||||
} // namespace ircd
|
||||
|
||||
/*
|
||||
* This function sets up the IRCd, handlers, and then returns without blocking.
|
||||
* Pass your io_service instance, it will share it with the rest of your program.
|
||||
* An exception will be thrown on error.
|
||||
*/
|
||||
void
|
||||
ircd::init(boost::asio::io_service &io_service)
|
||||
{
|
||||
ircd::ios = &io_service;
|
||||
|
||||
init_sys();
|
||||
init_sigs();
|
||||
|
||||
// The log is available, but it is console-only until conf opens files.
|
||||
log::init();
|
||||
log::mark("log started");
|
||||
|
||||
// initialise operhash fairly early.
|
||||
//init_operhash();
|
||||
|
||||
me.localClient = &meLocalUser;
|
||||
//rb_dlinkAddTail(&me, &me.node, &global_client_list);
|
||||
|
||||
//init_builtin_capabs();
|
||||
//default_server_capabs = CAP_MASK;
|
||||
//newconf_init();
|
||||
//init_s_conf();
|
||||
//init_s_newconf();
|
||||
//init_hash();
|
||||
//init_host_hash();
|
||||
//client::init();
|
||||
//init_hook();
|
||||
//chan::init();
|
||||
//initclass();
|
||||
//whowas::init();
|
||||
//init_reject();
|
||||
//cache::init();
|
||||
//init_monitor();
|
||||
//chan::mode::init();
|
||||
//init_authd(); /* Start up authd. */
|
||||
//init_dns(); /* Start up DNS query system */
|
||||
|
||||
//privilegeset_set_new("default", "", 0);
|
||||
|
||||
//read_conf_files(true); /* cold start init conf files */
|
||||
|
||||
//mods::autoload();
|
||||
//supported::init();
|
||||
//init_bandb();
|
||||
//init_ssld();
|
||||
//init_wsockd();
|
||||
//rehash_bans();
|
||||
|
||||
//default_server_capabs &= ~CAP_ZIP; // Set up default_server_capabs
|
||||
//initialize_global_set_options();
|
||||
/*
|
||||
if(ServerInfo.name == NULL)
|
||||
throw error("no server name specified in serverinfo block.");
|
||||
|
||||
rb_strlcpy(me.name, ServerInfo.name, sizeof(me.name));
|
||||
|
||||
if(ServerInfo.sid[0] == '\0')
|
||||
throw error("no server sid specified in serverinfo block.");
|
||||
|
||||
rb_strlcpy(me.id, ServerInfo.sid, sizeof(me.id));
|
||||
//client::init_uid();
|
||||
|
||||
// serverinfo{} description must exist. If not, error out.
|
||||
if(ServerInfo.description == NULL)
|
||||
throw error("no server description specified in serverinfo block.");
|
||||
|
||||
rb_strlcpy(me.info, ServerInfo.description, sizeof(me.info));
|
||||
*/
|
||||
/*
|
||||
if(ServerInfo.ssl_cert != NULL)
|
||||
{
|
||||
rlim.rlim_cur = rlim.rlim_max;
|
||||
setrlimit(RLIMIT_CORE, &rlim);
|
||||
// just do the rb_setup_ssl_server to validate the config
|
||||
if(!rb_setup_ssl_server(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list))
|
||||
{
|
||||
ilog(L_MAIN, "WARNING: Unable to setup SSL.");
|
||||
ircd_ssl_ok = false;
|
||||
}
|
||||
else
|
||||
ircd_ssl_ok = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
|
||||
static void
|
||||
ircd_log_cb(const char *str)
|
||||
{
|
||||
ilog(L_MAIN, "librb reports: %s", str);
|
||||
}
|
||||
//me.from = &me;
|
||||
//me.servptr = &me;
|
||||
//set_me(me);
|
||||
//make_serv(me);
|
||||
//add_to_client_hash(me.name, &me);
|
||||
//add_to_id_hash(me.id, &me);
|
||||
//nameinfo(serv(me)) = cache::serv::connect(me.name, me.info);
|
||||
|
||||
static void
|
||||
ircd_restart_cb(const char *str)
|
||||
{
|
||||
inotice("librb has called the restart callback: %s", str);
|
||||
restart(str);
|
||||
//rb_dlinkAddAlloc(&me, &global_serv_list);
|
||||
|
||||
//check_class();
|
||||
//cache::help::load();
|
||||
|
||||
//configure_authd();
|
||||
|
||||
/* We want try_connections to be called as soon as possible now! -- adrian */
|
||||
/* No, 'cause after a restart it would cause all sorts of nick collides */
|
||||
/* um. by waiting even longer, that just means we have even *more*
|
||||
* nick collisions. what a stupid idea. set an event for the IO loop --fl
|
||||
*/
|
||||
// rb_event_addish("try_connections", try_connections, NULL, STARTUP_CONNECTIONS_TIME);
|
||||
// rb_event_addonce("try_connections_startup", try_connections, NULL, 2);
|
||||
// rb_event_add("check_rehash", check_rehash, NULL, 3);
|
||||
// rb_event_addish("reseed_srand", seed_random, NULL, 300); /* reseed every 10 minutes */
|
||||
|
||||
// if(splitmode)
|
||||
// check_splitmode_ev = rb_event_add("check_splitmode", chan::check_splitmode, NULL, 5);
|
||||
|
||||
log::info("IRCd initialization completed successfully.");
|
||||
}
|
||||
|
||||
/*
|
||||
* Why EXIT_FAILURE here?
|
||||
* Because if ircd_die_cb() is called it's because of a fatal
|
||||
* error inside libcharybdis, and we don't know how to handle the
|
||||
* exception, so it is logical to return a FAILURE exit code here.
|
||||
* --nenolod
|
||||
* init_sys
|
||||
*
|
||||
* inputs - boot_daemon flag
|
||||
* output - none
|
||||
* side effects - if boot_daemon flag is not set, don't daemonize
|
||||
*/
|
||||
static void
|
||||
ircd_die_cb(const char *str)
|
||||
void
|
||||
ircd::init_sys()
|
||||
{
|
||||
if(str != NULL)
|
||||
{
|
||||
/* Try to get the message out to currently logged in operators. */
|
||||
sendto_realops_snomask(sno::GENERAL, L_NETWIDE, "librb has called the die callback..aborting: %s", str);
|
||||
inotice("librb has called the die callback..aborting: %s", str);
|
||||
}
|
||||
else
|
||||
inotice("librb has called the die callback..aborting");
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
/*
|
||||
* Setup corefile size immediately after boot -kre
|
||||
*/
|
||||
#ifdef HAVE_SYS_RESOURCE_H
|
||||
struct rlimit rlim; /* resource limits */
|
||||
|
||||
/* Set corefilesize to maximum */
|
||||
if(!getrlimit(RLIMIT_CORE, &rlim))
|
||||
{
|
||||
rlim.rlim_cur = rlim.rlim_max;
|
||||
setrlimit(RLIMIT_CORE, &rlim);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) && defined(RLIMIT_NOFILE) && defined(HAVE_SYS_RESOURCE_H)
|
||||
struct rlimit limit;
|
||||
|
||||
if(!getrlimit(RLIMIT_NOFILE, &limit))
|
||||
maxconnections = limit.rlim_cur;
|
||||
else
|
||||
maxconnections = MAXCONNECTIONS;
|
||||
#else
|
||||
maxconnections = MAXCONNECTIONS;
|
||||
#endif
|
||||
|
||||
rb_set_time();
|
||||
rb_init_prng(NULL, RB_PRNG_DEFAULT);
|
||||
seed_random();
|
||||
}
|
||||
|
||||
struct ev_entry *check_splitmode_ev = NULL;
|
||||
|
||||
static int
|
||||
seed_with_urandom(void)
|
||||
static bool
|
||||
seed_with_urandom()
|
||||
{
|
||||
unsigned int seed;
|
||||
int fd;
|
||||
|
@ -309,15 +338,15 @@ seed_with_urandom(void)
|
|||
{
|
||||
close(fd);
|
||||
srand(seed);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
seed_with_clock(void)
|
||||
seed_with_clock()
|
||||
{
|
||||
const struct timeval *tv;
|
||||
rb_set_time();
|
||||
|
@ -325,8 +354,8 @@ seed_with_clock(void)
|
|||
srand(tv->tv_sec ^ (tv->tv_usec | (getpid() << 20)));
|
||||
}
|
||||
|
||||
static void
|
||||
seed_random(void *unused)
|
||||
void
|
||||
ircd::seed_random()
|
||||
{
|
||||
unsigned int seed;
|
||||
if(rb_get_random(&seed, sizeof(seed)) == -1)
|
||||
|
@ -338,177 +367,67 @@ seed_random(void *unused)
|
|||
srand(seed);
|
||||
}
|
||||
|
||||
/*
|
||||
* main
|
||||
*
|
||||
* Initializes the IRCd.
|
||||
*
|
||||
* Inputs - number of commandline args, args themselves
|
||||
* Outputs - none
|
||||
* Side Effects - this is where the ircd gets going right now
|
||||
*/
|
||||
int
|
||||
run()
|
||||
static void
|
||||
sigfd_handle_sigusr2()
|
||||
{
|
||||
init_sys();
|
||||
rb_set_time();
|
||||
|
||||
/*
|
||||
* Setup corefile size immediately after boot -kre
|
||||
*/
|
||||
setup_corefile();
|
||||
|
||||
/* initialise operhash fairly early. */
|
||||
init_operhash();
|
||||
|
||||
me.localClient = &meLocalUser;
|
||||
rb_dlinkAddTail(&me, &me.node, &global_client_list);
|
||||
|
||||
memset(&Count, 0, sizeof(Count));
|
||||
memset(&ServerInfo, 0, sizeof(ServerInfo));
|
||||
memset(&AdminInfo, 0, sizeof(AdminInfo));
|
||||
memset(&ServerStats, 0, sizeof(struct ServerStatistics));
|
||||
|
||||
setup_signals();
|
||||
|
||||
server_state_foreground = true;
|
||||
|
||||
/* Check if there is pidfile and daemon already running */
|
||||
if(!testing_conf)
|
||||
{
|
||||
inotice("starting %s ...", info::version.c_str());
|
||||
inotice("%s", rb_lib_version());
|
||||
}
|
||||
|
||||
/* Init the event subsystem */
|
||||
rb_lib_init(ircd_log_cb, ircd_restart_cb, ircd_die_cb, false, maxconnections, DNODE_HEAP_SIZE, FD_HEAP_SIZE);
|
||||
rb_linebuf_init(LINEBUF_HEAP_SIZE);
|
||||
|
||||
rb_init_prng(NULL, RB_PRNG_DEFAULT);
|
||||
|
||||
seed_random(NULL);
|
||||
|
||||
init_builtin_capabs();
|
||||
default_server_capabs = CAP_MASK;
|
||||
|
||||
newconf_init();
|
||||
init_s_conf();
|
||||
init_s_newconf();
|
||||
|
||||
log::init();
|
||||
log::mark("log started");
|
||||
|
||||
init_hash();
|
||||
init_host_hash();
|
||||
client::init();
|
||||
init_hook();
|
||||
chan::init();
|
||||
initclass();
|
||||
whowas::init();
|
||||
init_reject();
|
||||
cache::init();
|
||||
init_monitor();
|
||||
chan::mode::init();
|
||||
|
||||
init_authd(); /* Start up authd. */
|
||||
init_dns(); /* Start up DNS query system */
|
||||
|
||||
privilegeset_set_new("default", "", 0);
|
||||
|
||||
if (testing_conf)
|
||||
fprintf(stderr, "\nBeginning config test\n");
|
||||
read_conf_files(true); /* cold start init conf files */
|
||||
|
||||
mods::autoload();
|
||||
|
||||
supported::init();
|
||||
|
||||
init_bandb();
|
||||
init_ssld();
|
||||
init_wsockd();
|
||||
|
||||
rehash_bans();
|
||||
|
||||
initialize_server_capabs(); /* Set up default_server_capabs */
|
||||
initialize_global_set_options();
|
||||
|
||||
if(ServerInfo.name == NULL)
|
||||
{
|
||||
ierror("no server name specified in serverinfo block.");
|
||||
return -1;
|
||||
}
|
||||
rb_strlcpy(me.name, ServerInfo.name, sizeof(me.name));
|
||||
|
||||
if(ServerInfo.sid[0] == '\0')
|
||||
{
|
||||
ierror("no server sid specified in serverinfo block.");
|
||||
return -2;
|
||||
}
|
||||
rb_strlcpy(me.id, ServerInfo.sid, sizeof(me.id));
|
||||
client::init_uid();
|
||||
|
||||
/* serverinfo{} description must exist. If not, error out. */
|
||||
if(ServerInfo.description == NULL)
|
||||
{
|
||||
ierror("no server description specified in serverinfo block.");
|
||||
return -3;
|
||||
}
|
||||
rb_strlcpy(me.info, ServerInfo.description, sizeof(me.info));
|
||||
|
||||
if(ServerInfo.ssl_cert != NULL)
|
||||
{
|
||||
/* just do the rb_setup_ssl_server to validate the config */
|
||||
if(!rb_setup_ssl_server(ServerInfo.ssl_cert, ServerInfo.ssl_private_key, ServerInfo.ssl_dh_params, ServerInfo.ssl_cipher_list))
|
||||
{
|
||||
ilog(L_MAIN, "WARNING: Unable to setup SSL.");
|
||||
ircd_ssl_ok = false;
|
||||
}
|
||||
else
|
||||
ircd_ssl_ok = true;
|
||||
}
|
||||
|
||||
if (testing_conf)
|
||||
{
|
||||
fprintf(stderr, "\nConfig testing complete.\n");
|
||||
fflush(stderr);
|
||||
return 0; /* Why? We want the launcher to exit out. */
|
||||
}
|
||||
|
||||
me.from = &me;
|
||||
me.servptr = &me;
|
||||
set_me(me);
|
||||
make_serv(me);
|
||||
add_to_client_hash(me.name, &me);
|
||||
add_to_id_hash(me.id, &me);
|
||||
nameinfo(serv(me)) = cache::serv::connect(me.name, me.info);
|
||||
|
||||
rb_dlinkAddAlloc(&me, &global_serv_list);
|
||||
|
||||
check_class();
|
||||
cache::help::load();
|
||||
|
||||
log::open();
|
||||
|
||||
configure_authd();
|
||||
|
||||
/* We want try_connections to be called as soon as possible now! -- adrian */
|
||||
/* No, 'cause after a restart it would cause all sorts of nick collides */
|
||||
/* um. by waiting even longer, that just means we have even *more*
|
||||
* nick collisions. what a stupid idea. set an event for the IO loop --fl
|
||||
*/
|
||||
rb_event_addish("try_connections", try_connections, NULL, STARTUP_CONNECTIONS_TIME);
|
||||
rb_event_addonce("try_connections_startup", try_connections, NULL, 2);
|
||||
rb_event_add("check_rehash", check_rehash, NULL, 3);
|
||||
rb_event_addish("reseed_srand", seed_random, NULL, 300); /* reseed every 10 minutes */
|
||||
|
||||
if(splitmode)
|
||||
check_splitmode_ev = rb_event_add("check_splitmode", chan::check_splitmode, NULL, 5);
|
||||
|
||||
print_startup(getpid());
|
||||
|
||||
rb_lib_loop(0);
|
||||
|
||||
return 0;
|
||||
// dorehashbans
|
||||
// doremotd
|
||||
}
|
||||
|
||||
} // namespace ircd
|
||||
static void
|
||||
sigfd_handle_sigusr1()
|
||||
{
|
||||
// dorehash (no longer hangup!)
|
||||
}
|
||||
|
||||
static void
|
||||
sigfd_handle_sigquit()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
sigfd_handle_sigterm()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ircd::sigfd_handler(const boost::system::error_code &ec,
|
||||
int signum)
|
||||
{
|
||||
switch(ec.value())
|
||||
{
|
||||
using namespace boost::system::errc;
|
||||
|
||||
case success: break;
|
||||
case operation_canceled: return;
|
||||
default:
|
||||
throw error("Signal handler (%d): %s",
|
||||
signum,
|
||||
ec.message().c_str());
|
||||
}
|
||||
|
||||
switch(signum)
|
||||
{
|
||||
case SIGTERM: sigfd_handle_sigterm(); return;
|
||||
case SIGQUIT: sigfd_handle_sigquit(); return;
|
||||
case SIGUSR1: sigfd_handle_sigusr1(); break;
|
||||
case SIGUSR2: sigfd_handle_sigusr2(); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if(sigfd)
|
||||
sigfd->async_wait(sigfd_handler);
|
||||
}
|
||||
|
||||
void
|
||||
ircd::init_sigs()
|
||||
{
|
||||
sigfd.reset(new boost::asio::signal_set(*ios));
|
||||
sigfd->add(SIGTERM);
|
||||
sigfd->add(SIGQUIT);
|
||||
sigfd->add(SIGUSR1);
|
||||
sigfd->add(SIGUSR2);
|
||||
sigfd->async_wait(sigfd_handler);
|
||||
}
|
||||
|
|
|
@ -1,193 +0,0 @@
|
|||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, src/ircd_signal.c
|
||||
* Copyright (C) 1990 Jarkko Oikarinen and
|
||||
* University of Oulu, Computing Center
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
namespace ircd {
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
/*
|
||||
* dummy_handler - don't know if this is really needed but if alarm is still
|
||||
* being used we probably will
|
||||
*/
|
||||
static void
|
||||
dummy_handler(int sig)
|
||||
{
|
||||
/* Empty */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sigchld_handler(int sig)
|
||||
{
|
||||
int status, olderrno;
|
||||
|
||||
olderrno = errno;
|
||||
while (waitpid(-1, &status, WNOHANG) > 0)
|
||||
;
|
||||
errno = olderrno;
|
||||
}
|
||||
|
||||
/*
|
||||
* sigterm_handler - exit the server
|
||||
*/
|
||||
static void
|
||||
sigterm_handler(int sig) __attribute__((noreturn));
|
||||
|
||||
static void
|
||||
sigterm_handler(int sig)
|
||||
{
|
||||
ircd_shutdown("Received SIGTERM");
|
||||
}
|
||||
|
||||
/*
|
||||
* sighup_handler - reread the server configuration
|
||||
*/
|
||||
static void
|
||||
sighup_handler(int sig)
|
||||
{
|
||||
dorehash = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* sigusr1_handler - reread the motd file
|
||||
*/
|
||||
static void
|
||||
sigusr1_handler(int sig)
|
||||
{
|
||||
doremotd = true;
|
||||
}
|
||||
|
||||
static void
|
||||
sigusr2_handler(int sig)
|
||||
{
|
||||
dorehashbans = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* sigint_handler - restart the server
|
||||
*/
|
||||
static void
|
||||
sigint_handler(int sig)
|
||||
{
|
||||
static bool restarting = false;
|
||||
|
||||
if(server_state_foreground)
|
||||
{
|
||||
log::critical("Server exiting on SIGINT");
|
||||
exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
log::critical("Server Restarting on SIGINT");
|
||||
if(!restarting)
|
||||
{
|
||||
restarting = true;
|
||||
server_reboot();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* setup_signals - initialize signal handlers for server
|
||||
*/
|
||||
void
|
||||
setup_signals()
|
||||
{
|
||||
sigset_t sigs;
|
||||
struct sigaction act;
|
||||
|
||||
sigemptyset(&sigs);
|
||||
act.sa_flags = 0;
|
||||
act.sa_handler = SIG_IGN;
|
||||
sigemptyset(&act.sa_mask);
|
||||
sigaddset(&act.sa_mask, SIGPIPE);
|
||||
sigaddset(&act.sa_mask, SIGALRM);
|
||||
#ifdef SIGTRAP
|
||||
sigaddset(&act.sa_mask, SIGTRAP);
|
||||
#endif
|
||||
|
||||
# ifdef SIGWINCH
|
||||
sigaddset(&act.sa_mask, SIGWINCH);
|
||||
sigaction(SIGWINCH, &act, 0);
|
||||
# endif
|
||||
sigaction(SIGPIPE, &act, 0);
|
||||
#ifdef SIGTRAP
|
||||
sigaction(SIGTRAP, &act, 0);
|
||||
#endif
|
||||
|
||||
act.sa_handler = dummy_handler;
|
||||
sigaction(SIGALRM, &act, 0);
|
||||
sigaddset(&sigs, SIGALRM);
|
||||
|
||||
act.sa_handler = sighup_handler;
|
||||
sigemptyset(&act.sa_mask);
|
||||
sigaddset(&act.sa_mask, SIGHUP);
|
||||
sigaction(SIGHUP, &act, 0);
|
||||
sigaddset(&sigs, SIGHUP);
|
||||
|
||||
act.sa_handler = sigint_handler;
|
||||
sigaddset(&act.sa_mask, SIGINT);
|
||||
sigaction(SIGINT, &act, 0);
|
||||
sigaddset(&sigs, SIGINT);
|
||||
|
||||
act.sa_handler = sigterm_handler;
|
||||
sigaddset(&act.sa_mask, SIGTERM);
|
||||
sigaction(SIGTERM, &act, 0);
|
||||
sigaddset(&sigs, SIGTERM);
|
||||
|
||||
act.sa_handler = sigusr1_handler;
|
||||
sigaddset(&act.sa_mask, SIGUSR1);
|
||||
sigaction(SIGUSR1, &act, 0);
|
||||
sigaddset(&sigs, SIGUSR1);
|
||||
|
||||
act.sa_handler = sigusr2_handler;
|
||||
sigaddset(&act.sa_mask, SIGUSR2);
|
||||
sigaction(SIGUSR2, &act, 0);
|
||||
sigaddset(&sigs, SIGUSR2);
|
||||
|
||||
act.sa_handler = sigchld_handler;
|
||||
sigaddset(&act.sa_mask, SIGCHLD);
|
||||
sigaction(SIGCHLD, &act, 0);
|
||||
sigaddset(&sigs, SIGCHLD);
|
||||
|
||||
sigprocmask(SIG_UNBLOCK, &sigs, NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void
|
||||
setup_signals()
|
||||
{
|
||||
/* this is a stub for mingw32 */
|
||||
}
|
||||
|
||||
void
|
||||
setup_reboot_signals()
|
||||
{
|
||||
/* this is a stub for mingw32 */
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
} // namespace ircd
|
|
@ -74,7 +74,7 @@ log::init()
|
|||
{
|
||||
//TODO: XXX: config + cmd control + other fancy stuff
|
||||
|
||||
add_top_conf("log", NULL, NULL, conf_log_table);
|
||||
//add_top_conf("log", NULL, NULL, conf_log_table);
|
||||
|
||||
console_err[CRITICAL] = true;
|
||||
console_err[ERROR] = true;
|
||||
|
@ -115,7 +115,7 @@ log::init()
|
|||
void
|
||||
log::fini()
|
||||
{
|
||||
remove_top_conf("log");
|
||||
//remove_top_conf("log");
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -73,5 +73,32 @@ server_reboot(void)
|
|||
exit(-1);
|
||||
}
|
||||
|
||||
void
|
||||
ircd_shutdown(const char *reason)
|
||||
{
|
||||
client::client *target_p;
|
||||
rb_dlink_node *ptr;
|
||||
|
||||
RB_DLINK_FOREACH(ptr, lclient_list.head)
|
||||
{
|
||||
target_p = (client::client *)ptr->data;
|
||||
|
||||
sendto_one(target_p, ":%s NOTICE %s :Server Terminating. %s",
|
||||
me.name, target_p->name, reason);
|
||||
}
|
||||
|
||||
RB_DLINK_FOREACH(ptr, serv_list.head)
|
||||
{
|
||||
target_p = (client::client *)ptr->data;
|
||||
|
||||
sendto_one(target_p, ":%s ERROR :Terminated by %s",
|
||||
me.name, reason);
|
||||
}
|
||||
|
||||
log::critical("Server Terminating. %s", reason);
|
||||
log::close();
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
} // namespace ircd
|
||||
|
|
Loading…
Reference in a new issue