]> arthur.barton.de Git - ngircd-alex.git/blobdiff - src/ngircd/conn.c
Add new _IRC_ARGC_EQ_OR_RETURN_ macro to irc-macros.h
[ngircd-alex.git] / src / ngircd / conn.c
index 378509f96f09bc35eb9e3ebc2eb12140c24509fb..3c1427d5461272ac83a68c21e769f557bc80d472 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * 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
@@ -121,6 +121,8 @@ static void cb_Read_Resolver_Result PARAMS((int sock, UNUSED short what));
 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).
@@ -137,7 +139,7 @@ static int
 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
@@ -149,7 +151,7 @@ my_sd_listen_fds(void)
        e = getenv("LISTEN_FDS");
        if (!e || !*e)
                return -1;
-       count = atol(e);
+       count = atoi(e);
        unsetenv("LISTEN_FDS");
 
        return count;
@@ -530,8 +532,9 @@ Conn_InitListeners( void )
 {
        /* 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);
 
@@ -547,6 +550,36 @@ Conn_InitListeners( void )
                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,
@@ -555,7 +588,8 @@ Conn_InitListeners( void )
                                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;
@@ -906,6 +940,15 @@ Conn_Handler(void)
                            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)
@@ -1267,6 +1310,8 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie
                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 */
 
 
@@ -1638,6 +1683,7 @@ static void
 Account_Connection(void)
 {
        NumConnections++;
+       idle_t = 0;
        if (NumConnections > NumConnectionsMax)
                NumConnectionsMax = NumConnections;
        LogDebug("Total number of connections now %lu (max %lu).",