]> Pileus Git - ~andy/lamechat/commitdiff
Add IRC timeout.
authorAndy Spencer <andy753421@gmail.com>
Tue, 20 Feb 2018 02:53:06 +0000 (02:53 +0000)
committerAndy Spencer <andy753421@gmail.com>
Tue, 20 Feb 2018 03:46:58 +0000 (03:46 +0000)
irc.c
test.sh

diff --git a/irc.c b/irc.c
index b2bbeeee4e79450ea803a34d0c4978160a365f25..f26c19657ea7b280ad8d9c751ad859adc5228ee7 100644 (file)
--- a/irc.c
+++ b/irc.c
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#define _GNU_SOURCE
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include <stdint.h>
 #include <string.h>
 #include <ctype.h>
+#include <unistd.h>
+
+#include <sys/timerfd.h>
 
 #include "util.h"
 #include "conf.h"
@@ -72,6 +78,7 @@ typedef struct {
        server_t      server;
 
        int           connect;
+       int           timeout;
        int           noverify;
        const char   *host;
        int           port;
@@ -80,6 +87,9 @@ typedef struct {
        const char   *auth;
        const char   *pass;
 
+       int           timer;
+       poll_t        poll;
+
        irc_user_t    myself;
        irc_channel_t system;
        net_t         net;
@@ -251,12 +261,12 @@ static void parse_line(irc_server_t *srv, const char *line,
 }
 
 /* Callback functions */
-static void irc_run(irc_server_t *srv, const char *line);
+static void irc_run(irc_server_t *srv, int idle, const char *line);
 
 static void on_send(void *_srv)
 {
        irc_server_t *srv = _srv;
-       irc_run(srv, "");
+       irc_run(srv, 0, "");
 }
 
 static void on_recv(void *_srv, char *buf, int len)
@@ -271,12 +281,12 @@ static void on_recv(void *_srv, char *buf, int len)
                if (buf[i] == '\n' || buf[i] == '\r') {
                        srv->line[srv->pos-1] = '\0';
                        if (srv->pos > 1)
-                               irc_run(srv, srv->line);
+                               irc_run(srv, 0, srv->line);
                        srv->pos = 0;
                }
        }
 
-       irc_run(srv, "");
+       irc_run(srv, 0, "");
 }
 
 static void on_err(void *_srv, int err)
@@ -286,8 +296,16 @@ static void on_err(void *_srv, int err)
        srv->state = IRC_DEAD;
 }
 
+static void on_timer(void *_srv)
+{
+       uint64_t buf;
+       irc_server_t *srv = _srv;
+       while (read(srv->timer, &buf, sizeof(buf)) > 0)
+               irc_run(srv, 1, "");
+}
+
 /* IRC State machine */
-static void irc_run(irc_server_t *srv, const char *line)
+static void irc_run(irc_server_t *srv, int idle, const char *line)
 {
        static irc_command_t _cmd;
        const char *cmd  = _cmd.cmd;
@@ -306,6 +324,18 @@ static void irc_run(irc_server_t *srv, const char *line)
                srv->net.err  = on_err;
                srv->net.data = srv;
 
+               srv->timer = timerfd_create(CLOCK_MONOTONIC,
+                                           TFD_NONBLOCK|TFD_CLOEXEC);
+               if (srv->timer < 0)
+                       error("creating timer fd");
+               int sec  = srv->timeout > 0 ?  srv->timeout : 0;
+               int nsec = srv->timeout < 0 ? -srv->timeout : 0;
+               struct timespec tspec = {sec, nsec};
+               struct itimerspec itspec = {tspec, tspec};
+               timerfd_settime(srv->timer, 0, &itspec, NULL);
+               poll_add(&srv->poll, srv->timer, on_timer, srv);
+               poll_ctl(&srv->poll, 1, 0, 1);
+
                srv_notice(srv, "Joining Server: %s", srv->server.name);
                net_open(&srv->net, srv->host, srv->port);
 
@@ -315,6 +345,12 @@ static void irc_run(irc_server_t *srv, const char *line)
                        srv->state = IRC_SEND_TLS;
        }
 
+       /* Idle handling */
+       if (srv->state > IRC_CONNECT && idle) {
+               debug("irc: idle");
+               net_print(&srv->net, "PING %s\n", srv->host);
+       }
+
        /* Start TLS */
        if (srv->state == IRC_SEND_TLS) {
                if (net_print(&srv->net, "CAP REQ :tls\n"))
@@ -467,11 +503,6 @@ void irc_init(void)
                        continue;
 
                irc_server_t *srv = (irc_server_t*)cur;
-               srv->system.channel.server = &srv->server;
-               srv->system.channel.name   = srv->server.name;
-
-               srv->myself.user.server = &srv->server;
-               srv->myself.user.name = strcopy(srv->nick);
 
                if (!srv->port)
                        srv->port = srv->tls ? 6697 : 6667;
@@ -479,9 +510,18 @@ void irc_init(void)
                        srv->nick = strcopy(getenv("USER"));
                if (!srv->nick)
                        srv->nick = strcopy("lameuser");
+               if (!srv->timeout)
+                       srv->timeout = 60;
+
+               srv->system.channel.server = &srv->server;
+               srv->system.channel.name   = srv->server.name;
+
+               srv->myself.user.server = &srv->server;
+               srv->myself.user.name = strcopy(srv->nick);
+
                if (srv->connect) {
                        srv->state = IRC_CONNECT;
-                       irc_run(srv, "");
+                       irc_run(srv, 0, "");
                }
        }
        for (channel_t *cur = channels; cur; cur = cur->next) {
@@ -510,6 +550,8 @@ void irc_config(server_t *server, channel_t *channel,
                }
                else if (match(key, "connect"))
                        srv->connect = get_bool(value);
+               else if (match(key, "timeout"))
+                       srv->timeout = get_number(value);
                else if (match(key, "noverify"))
                        srv->noverify = get_bool(value);
                else if (match(key, "host"))
diff --git a/test.sh b/test.sh
index 34a178a41f78108f33c5a38777952d658ea3875e..953f9372b7ef5fe19fa86402f9456d154afd6ad9 100755 (executable)
--- a/test.sh
+++ b/test.sh
@@ -356,6 +356,26 @@ test_irc_startls() {
        EOF
 }
 
+test_irc_timeout() {
+       setup -c -s 6667 <<-EOF
+               [server "local"]
+                   protocol = irc
+                   connect  = true
+                   timeout  = -10000000
+                   host     = "localhost"
+                   nick     = "andy"
+       EOF
+       server 6667 <<-EOF
+               > CAP REQ :tls
+               < CAP NAK
+               > CAP END
+               > USER *
+               > NICK *
+               < :lamechat 001 andy :Welcome to lamechat!
+               > PING localhost
+       EOF
+}
+
 test_irc_options() {
        unset USER
        setup -c -x 12345 <<-EOF