ircd/main.cpp
#include "common.hpp"
#include "config.hpp"
#include "sock.hpp"
#include "poll.hpp"
#include "server.hpp"
#include "nickserv.hpp"
#include "ssl.hpp"
#include <unistd.h>
#include <assert.h>
int main(int argc, char** argv) {
// basic setup
update_now();
close(0);
close(1);
// parse config
bool systemd = false;
const char* conffile = NULL;
if (argc == 2) {
conffile = argv[1];
} else if (argc == 3) {
if (strcmp(argv[1], "--systemd") != 0) {
LOG("Unknown argument '%s'", argv[1]);
return 1;
}
systemd = true;
conffile = argv[2];
} else {
LOG("Usage: %s [--systemd] <config-file>", argv[0]);
return 1;
}
if (!parse_config(conffile)) {
log_usage();
return 1;
}
// handlers
register_signals();
// default-handlers - ssl?
io_handlers.pre_accept_handler = NULL;
io_handlers.accept_handler = &Client::createInst;
io_handlers.read_handler = &read;
io_handlers.write_handler = &write;
io_handlers.close_handler = &close;
#ifdef USE_OPENSSL
if (atoi(config.ssl.str)) {
if (!ssl_init(config.ssl_cert.str, config.ssl_key.str)) {
LOG("cannot initialize ssl");
ssl_deinit();
return 1;
}
io_handlers.pre_accept_handler = &SslClient::createInst;
io_handlers.read_handler = &SslClient::ssl_read;
io_handlers.write_handler = &SslClient::ssl_write;
io_handlers.close_handler = &SslClient::shutdown;
}
#endif
// listen on port(s)
std::vector<int> fds;
if (systemd) {
if (!socket_listen(fds)) return 1;
assert(fds.size());
LOG("inherited %zu listening ports, ignoring %zu configured ones...", fds.size(), config.port.strs.size());
} else {
assert(config.port.strs.size()); // mandatory config option(s)
for (std::vector<const char*>::const_iterator it = config.port.strs.begin(); it != config.port.strs.end(); ++it) {
int port = atoi(*it);
int fd = (port > 0)? socket_listen(port): -1;
if (fd == -1) return 1;
fds.push_back(fd);
LOG("listening on :%d...", port);
}
}
// drop privs & goto jail
if (!goto_jail(config.chroot_user.str, config.chroot_dir.str)) {
return 1;
}
// init
Server* server = new Server();
Poll* poll = Poll::getInst();
for (std::vector<int>::const_iterator it = fds.begin(); it != fds.end(); ++it) {
poll->add(*it, &socket_accept, EVENT_IN);
}
(void)NickServ::getInst(); // early init
// main loop
while (!SHUTDOWN) {
if (!poll->wait(1000)) break;
if (systemd && poll->num_fds() <= fds.size() && poll->last_event() < NOW - SOCK_TIMEOUT) {
LOG("idle timeout reached");
break;
}
usleep(100000); // event collect interval
}
LOG("shutting down");
// TODO: if (systemd) sd_notify(false, "STOPPING=1\n" "STATUS=Shutting down.");
// don't accept anymore & kick all clients & cleanup
while (fds.size()) {
poll->del(fds.back());
if (!systemd) { // keep inherited systemd fds open
close(fds.back());
}
fds.pop_back();
}
delete server;
delete poll;
delete NickServ::getInst();
#ifdef USE_OPENSSL
if (atoi(config.ssl.str)) {
ssl_deinit();
}
#endif
free_config();
return 0;
}