/*
* ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
+ * Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors.
*
* 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
static void cb_Connect_to_Server PARAMS((int sock, UNUSED short what));
static void cb_clientserver PARAMS((int sock, short what));
+time_t idle_t = 0;
+
/**
* Get number of sockets available from systemd(8).
my_sd_listen_fds(void)
{
const char *e;
- long count;
+ int count;
/* Check if LISTEN_PID exists; but we ignore the result, because
* normally ngircd forks a child before checking this, and therefore
e = getenv("LISTEN_FDS");
if (!e || !*e)
return -1;
- count = atol(e);
+ count = atoi(e);
unsetenv("LISTEN_FDS");
return count;
{
/* Initialize ports on which the server should accept connections */
unsigned int created = 0;
- char *copy, *listen_addr;
- int count, fd, i;
+ char *af_str, *copy, *listen_addr;
+ int count, fd, i, addr_len;
+ ng_ipaddr_t addr;
assert(Conf_ListenAddress);
LogDebug("Initializing %d systemd sockets ...", count);
for (i = 0; i < count; i++) {
fd = SD_LISTEN_FDS_START + i;
+ addr_len = (int)sizeof(addr);
+ getsockname(fd, (struct sockaddr *)&addr, (socklen_t*)&addr_len);
+#ifdef WANT_IPV6
+ if (addr.sin4.sin_family != AF_INET && addr.sin4.sin_family != AF_INET6)
+#else
+ if (addr.sin4.sin_family != AF_INET)
+#endif
+ {
+ /* Socket is of unsupported type! For example, systemd passed in
+ * an IPv6 socket but ngIRCd isn't compiled with IPv6 support. */
+ switch (addr.sin4.sin_family)
+ {
+ case AF_UNSPEC: af_str = "AF_UNSPEC"; break;
+ case AF_UNIX: af_str = "AF_UNIX"; break;
+ case AF_INET: af_str = "AF_INET"; break;
+#ifdef AF_INET6
+ case AF_INET6: af_str = "AF_INET6"; break;
+#endif
+#ifdef AF_NETLINK
+ case AF_NETLINK: af_str = "AF_NETLINK"; break;
+#endif
+ default: af_str = "unknown"; break;
+ }
+ Log(LOG_CRIT,
+ "Socket %d is of unsupported type \"%s\" (%d), have to ignore it!",
+ fd, af_str, addr.sin4.sin_family);
+ close(fd);
+ continue;
+ }
+
Init_Socket(fd);
if (!io_event_create(fd, IO_WANTREAD, cb_listen)) {
Log(LOG_ERR,
continue;
}
Log(LOG_INFO,
- "Initialized socket %d from systemd.", fd);
+ "Initialized socket %d from systemd(8): %s:%d.", fd,
+ ng_ipaddr_tostr(&addr), ng_ipaddr_getport(&addr));
created++;
}
return created;
PACKAGE_NAME);
exit(1);
}
+
+ /* Should ngIRCd timeout when idle? */
+ if (Conf_IdleTimeout > 0 && NumConnectionsAccepted > 0
+ && idle_t > 0 && time(NULL) - idle_t >= Conf_IdleTimeout) {
+ LogDebug("Server idle timeout reached: %d second%s. Initiating shutdown ...",
+ Conf_IdleTimeout,
+ Conf_IdleTimeout == 1 ? "" : "s");
+ NGIRCd_SignalQuit = true;
+ }
}
if (NGIRCd_SignalQuit)
NumConnections--;
LogDebug("Shutdown of connection %d completed, %ld connection%s left.",
Idx, NumConnections, NumConnections != 1 ? "s" : "");
+
+ idle_t = NumConnections > 0 ? 0 : time(NULL);
} /* Conn_Close */
Account_Connection(void)
{
NumConnections++;
+ idle_t = 0;
if (NumConnections > NumConnectionsMax)
NumConnectionsMax = NumConnections;
LogDebug("Total number of connections now %lu (max %lu).",