itentative reconnection support - irc - Unnamed repository; edit this file 'description' to name the repository. Err vernunftzentrum.de 70 hgit clone git://vernunftzentrum.de/irc.git URL:git://vernunftzentrum.de/irc.git vernunftzentrum.de 70 1Log /ckeen/repos/irc/log.gph vernunftzentrum.de 70 1Files /ckeen/repos/irc/files.gph vernunftzentrum.de 70 1Refs /ckeen/repos/irc/refs.gph vernunftzentrum.de 70 1README /ckeen/repos/irc/file/README.gph vernunftzentrum.de 70 i--- Err vernunftzentrum.de 70 1commit 3bb53c314db1eede1b9359c9e7886105cedd8fc3 /ckeen/repos/irc/commit/3bb53c314db1eede1b9359c9e7886105cedd8fc3.gph vernunftzentrum.de 70 1parent 874cde6562f0c0817a6d14878269c4364cddb801 /ckeen/repos/irc/commit/874cde6562f0c0817a6d14878269c4364cddb801.gph vernunftzentrum.de 70 hAuthor: Quentin Carbonneaux URL:mailto:quentin.carbonneaux@yale.edu vernunftzentrum.de 70 iDate: Thu, 19 Jan 2017 11:10:01 -0500 Err vernunftzentrum.de 70 i Err vernunftzentrum.de 70 itentative reconnection support Err vernunftzentrum.de 70 i Err vernunftzentrum.de 70 iDiffstat: Err vernunftzentrum.de 70 i irc.c | 145 ++++++++++++++++++++----------- Err vernunftzentrum.de 70 i Err vernunftzentrum.de 70 i1 file changed, 94 insertions(+), 51 deletions(-) Err vernunftzentrum.de 70 i--- Err vernunftzentrum.de 70 1diff --git a/irc.c b/irc.c /ckeen/repos/irc/file/irc.c.gph vernunftzentrum.de 70 i@@ -39,6 +39,7 @@ enum { Err vernunftzentrum.de 70 i MaxChans = 16, Err vernunftzentrum.de 70 i BufSz = 2048, Err vernunftzentrum.de 70 i LogSz = 4096, Err vernunftzentrum.de 70 i+ MaxRecons = 10, /* -1 for infinitely many */ Err vernunftzentrum.de 70 i UtfSz = 4, Err vernunftzentrum.de 70 i RuneInvalid = 0xFFFD, Err vernunftzentrum.de 70 i }; Err vernunftzentrum.de 70 i@@ -58,6 +59,7 @@ static struct Chan { Err vernunftzentrum.de 70 i size_t sz; /* Size of buf. */ Err vernunftzentrum.de 70 i char high; /* Nick highlight. */ Err vernunftzentrum.de 70 i char new; /* New message. */ Err vernunftzentrum.de 70 i+ char join; /* Channel was 'j'-oined. */ Err vernunftzentrum.de 70 i } chl[MaxChans]; Err vernunftzentrum.de 70 i Err vernunftzentrum.de 70 i static int ssl; Err vernunftzentrum.de 70 i@@ -184,12 +186,7 @@ srd(void) Err vernunftzentrum.de 70 i rd = SSL_read(srv.ssl, p, BufSz - (p - l)); Err vernunftzentrum.de 70 i else Err vernunftzentrum.de 70 i rd = read(srv.fd, p, BufSz - (p - l)); Err vernunftzentrum.de 70 i- if (rd < 0) { Err vernunftzentrum.de 70 i- if (errno == EINTR) Err vernunftzentrum.de 70 i- return 1; Err vernunftzentrum.de 70 i- panic("IO error while reading."); Err vernunftzentrum.de 70 i- } Err vernunftzentrum.de 70 i- if (rd == 0) Err vernunftzentrum.de 70 i+ if (rd <= 0) Err vernunftzentrum.de 70 i return 0; Err vernunftzentrum.de 70 i p += rd; Err vernunftzentrum.de 70 i for (;;) { /* Cycle on all received lines. */ Err vernunftzentrum.de 70 i@@ -220,6 +217,16 @@ srd(void) Err vernunftzentrum.de 70 i } Err vernunftzentrum.de 70 i Err vernunftzentrum.de 70 i static void Err vernunftzentrum.de 70 i+sinit(const char *key, const char *nick, const char *user) Err vernunftzentrum.de 70 i+{ Err vernunftzentrum.de 70 i+ if (key) Err vernunftzentrum.de 70 i+ sndf("PASS %s", key); Err vernunftzentrum.de 70 i+ sndf("NICK %s", nick); Err vernunftzentrum.de 70 i+ sndf("USER %s 8 * :%s", user, user); Err vernunftzentrum.de 70 i+ sndf("MODE %s +i", nick); Err vernunftzentrum.de 70 i+} Err vernunftzentrum.de 70 i+ Err vernunftzentrum.de 70 i+static char * Err vernunftzentrum.de 70 i dial(const char *host, const char *service) Err vernunftzentrum.de 70 i { Err vernunftzentrum.de 70 i struct addrinfo hints, *res = NULL, *rp; Err vernunftzentrum.de 70 i@@ -230,7 +237,7 @@ dial(const char *host, const char *service) Err vernunftzentrum.de 70 i hints.ai_flags = AI_NUMERICSERV; /* avoid name lookup for port */ Err vernunftzentrum.de 70 i hints.ai_socktype = SOCK_STREAM; Err vernunftzentrum.de 70 i if ((e = getaddrinfo(host, service, &hints, &res))) Err vernunftzentrum.de 70 i- panic("Getaddrinfo failed."); Err vernunftzentrum.de 70 i+ return "Getaddrinfo failed."; Err vernunftzentrum.de 70 i for (rp = res; rp; rp = rp->ai_next) { Err vernunftzentrum.de 70 i if ((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) Err vernunftzentrum.de 70 i continue; Err vernunftzentrum.de 70 i@@ -241,27 +248,62 @@ dial(const char *host, const char *service) Err vernunftzentrum.de 70 i break; Err vernunftzentrum.de 70 i } Err vernunftzentrum.de 70 i if (fd == -1) Err vernunftzentrum.de 70 i- panic("Cannot connect to host."); Err vernunftzentrum.de 70 i+ return "Cannot connect to host."; Err vernunftzentrum.de 70 i srv.fd = fd; Err vernunftzentrum.de 70 i if (ssl) { Err vernunftzentrum.de 70 i SSL_load_error_strings(); Err vernunftzentrum.de 70 i SSL_library_init(); Err vernunftzentrum.de 70 i srv.ctx = SSL_CTX_new(SSLv23_client_method()); Err vernunftzentrum.de 70 i if (!srv.ctx) Err vernunftzentrum.de 70 i- panic("Could not initialize ssl context."); Err vernunftzentrum.de 70 i+ return "Could not initialize ssl context."; Err vernunftzentrum.de 70 i srv.ssl = SSL_new(srv.ctx); Err vernunftzentrum.de 70 i if (SSL_set_fd(srv.ssl, srv.fd) == 0 Err vernunftzentrum.de 70 i || SSL_connect(srv.ssl) != 1) Err vernunftzentrum.de 70 i- panic("Could not connect with ssl."); Err vernunftzentrum.de 70 i+ return "Could not connect with ssl."; Err vernunftzentrum.de 70 i } Err vernunftzentrum.de 70 i freeaddrinfo(res); Err vernunftzentrum.de 70 i+ return 0; Err vernunftzentrum.de 70 i+} Err vernunftzentrum.de 70 i+ Err vernunftzentrum.de 70 i+static void Err vernunftzentrum.de 70 i+hangup(void) Err vernunftzentrum.de 70 i+{ Err vernunftzentrum.de 70 i+ if (srv.ssl) { Err vernunftzentrum.de 70 i+ SSL_shutdown(srv.ssl); Err vernunftzentrum.de 70 i+ SSL_free(srv.ssl); Err vernunftzentrum.de 70 i+ srv.ssl = 0; Err vernunftzentrum.de 70 i+ } Err vernunftzentrum.de 70 i+ if (srv.fd) { Err vernunftzentrum.de 70 i+ close(srv.fd); Err vernunftzentrum.de 70 i+ srv.fd = 0; Err vernunftzentrum.de 70 i+ } Err vernunftzentrum.de 70 i+ if (srv.ctx) { Err vernunftzentrum.de 70 i+ SSL_CTX_free(srv.ctx); Err vernunftzentrum.de 70 i+ srv.ctx = 0; Err vernunftzentrum.de 70 i+ } Err vernunftzentrum.de 70 i+} Err vernunftzentrum.de 70 i+ Err vernunftzentrum.de 70 i+static inline int Err vernunftzentrum.de 70 i+chfind(const char *name) Err vernunftzentrum.de 70 i+{ Err vernunftzentrum.de 70 i+ int i; Err vernunftzentrum.de 70 i+ Err vernunftzentrum.de 70 i+ assert(name); Err vernunftzentrum.de 70 i+ for (i = nch - 1; i > 0; i--) Err vernunftzentrum.de 70 i+ if (!strcmp(chl[i].name, name)) Err vernunftzentrum.de 70 i+ break; Err vernunftzentrum.de 70 i+ return i; Err vernunftzentrum.de 70 i } Err vernunftzentrum.de 70 i Err vernunftzentrum.de 70 i static int Err vernunftzentrum.de 70 i-chadd(char *name, int change) Err vernunftzentrum.de 70 i+chadd(const char *name, int joined) Err vernunftzentrum.de 70 i { Err vernunftzentrum.de 70 i+ int n; Err vernunftzentrum.de 70 i+ Err vernunftzentrum.de 70 i if (nch >= MaxChans || strlen(name) >= ChanLen) Err vernunftzentrum.de 70 i return -1; Err vernunftzentrum.de 70 i+ if ((n = chfind(name)) > 0) Err vernunftzentrum.de 70 i+ return n; Err vernunftzentrum.de 70 i strcpy(chl[nch].name, name); Err vernunftzentrum.de 70 i chl[nch].sz = LogSz; Err vernunftzentrum.de 70 i chl[nch].buf = malloc(LogSz); Err vernunftzentrum.de 70 i@@ -269,25 +311,14 @@ chadd(char *name, int change) Err vernunftzentrum.de 70 i panic("Out of memory."); Err vernunftzentrum.de 70 i chl[nch].eol = chl[nch].buf; Err vernunftzentrum.de 70 i chl[nch].n = 0; Err vernunftzentrum.de 70 i- if (change) Err vernunftzentrum.de 70 i+ chl[nch].join = joined; Err vernunftzentrum.de 70 i+ if (joined) Err vernunftzentrum.de 70 i ch = nch; Err vernunftzentrum.de 70 i nch++; Err vernunftzentrum.de 70 i tdrawbar(); Err vernunftzentrum.de 70 i return nch; Err vernunftzentrum.de 70 i } Err vernunftzentrum.de 70 i Err vernunftzentrum.de 70 i-static inline int Err vernunftzentrum.de 70 i-chfind(char *name) Err vernunftzentrum.de 70 i-{ Err vernunftzentrum.de 70 i- int i; Err vernunftzentrum.de 70 i- Err vernunftzentrum.de 70 i- assert(name); Err vernunftzentrum.de 70 i- for (i = nch - 1; i > 0; i--) Err vernunftzentrum.de 70 i- if (!strcmp(chl[i].name, name)) Err vernunftzentrum.de 70 i- break; Err vernunftzentrum.de 70 i- return i; Err vernunftzentrum.de 70 i-} Err vernunftzentrum.de 70 i- Err vernunftzentrum.de 70 i static int Err vernunftzentrum.de 70 i chdel(char *name) Err vernunftzentrum.de 70 i { Err vernunftzentrum.de 70 i@@ -779,8 +810,10 @@ main(int argc, char *argv[]) Err vernunftzentrum.de 70 i const char *key = getenv("IRCPASS"); Err vernunftzentrum.de 70 i const char *server = SRV; Err vernunftzentrum.de 70 i const char *port = PORT; Err vernunftzentrum.de 70 i- int o; Err vernunftzentrum.de 70 i+ char *err; Err vernunftzentrum.de 70 i+ int o, reconn; Err vernunftzentrum.de 70 i Err vernunftzentrum.de 70 i+ signal(SIGPIPE, SIG_IGN); Err vernunftzentrum.de 70 i while ((o = getopt(argc, argv, "thk:n:u:s:p:l:")) >= 0) Err vernunftzentrum.de 70 i switch (o) { Err vernunftzentrum.de 70 i case 'h': Err vernunftzentrum.de 70 i@@ -817,14 +850,15 @@ main(int argc, char *argv[]) Err vernunftzentrum.de 70 i if (!user) Err vernunftzentrum.de 70 i user = "anonymous"; Err vernunftzentrum.de 70 i tinit(); Err vernunftzentrum.de 70 i- dial(server, port); Err vernunftzentrum.de 70 i- chadd("*server*", 1); Err vernunftzentrum.de 70 i- if (key) Err vernunftzentrum.de 70 i- sndf("PASS %s", key); Err vernunftzentrum.de 70 i- sndf("NICK %s", nick); Err vernunftzentrum.de 70 i- sndf("USER %s 8 * :%s", user, user); Err vernunftzentrum.de 70 i- sndf("MODE %s +i", nick); Err vernunftzentrum.de 70 i+ err = dial(server, port); Err vernunftzentrum.de 70 i+ if (err) Err vernunftzentrum.de 70 i+ panic(err); Err vernunftzentrum.de 70 i+ chadd(server, 0); Err vernunftzentrum.de 70 i+ sinit(key, nick, user); Err vernunftzentrum.de 70 i+ reconn = 0; Err vernunftzentrum.de 70 i while (!quit) { Err vernunftzentrum.de 70 i+ struct timeval t = {.tv_sec = 5}; Err vernunftzentrum.de 70 i+ struct Chan *c; Err vernunftzentrum.de 70 i fd_set rfs, wfs; Err vernunftzentrum.de 70 i int ret; Err vernunftzentrum.de 70 i Err vernunftzentrum.de 70 i@@ -833,18 +867,35 @@ main(int argc, char *argv[]) Err vernunftzentrum.de 70 i FD_ZERO(&wfs); Err vernunftzentrum.de 70 i FD_ZERO(&rfs); Err vernunftzentrum.de 70 i FD_SET(0, &rfs); Err vernunftzentrum.de 70 i- FD_SET(srv.fd, &rfs); Err vernunftzentrum.de 70 i- if (outp != outb) Err vernunftzentrum.de 70 i- FD_SET(srv.fd, &wfs); Err vernunftzentrum.de 70 i- ret = select(srv.fd + 1, &rfs, &wfs, 0, 0); Err vernunftzentrum.de 70 i+ if (!reconn) { Err vernunftzentrum.de 70 i+ FD_SET(srv.fd, &rfs); Err vernunftzentrum.de 70 i+ if (outp != outb) Err vernunftzentrum.de 70 i+ FD_SET(srv.fd, &wfs); Err vernunftzentrum.de 70 i+ } Err vernunftzentrum.de 70 i+ ret = select(srv.fd + 1, &rfs, &wfs, 0, &t); Err vernunftzentrum.de 70 i if (ret < 0) { Err vernunftzentrum.de 70 i if (errno == EINTR) Err vernunftzentrum.de 70 i continue; Err vernunftzentrum.de 70 i panic("Select failed."); Err vernunftzentrum.de 70 i } Err vernunftzentrum.de 70 i+ if (reconn) { Err vernunftzentrum.de 70 i+ hangup(); Err vernunftzentrum.de 70 i+ if (reconn++ == MaxRecons + 1) Err vernunftzentrum.de 70 i+ panic("Link lost."); Err vernunftzentrum.de 70 i+ pushf(0, "-!- Link lost, attempting reconnection..."); Err vernunftzentrum.de 70 i+ if (dial(server, port) != 0) Err vernunftzentrum.de 70 i+ continue; Err vernunftzentrum.de 70 i+ sinit(key, nick, user); Err vernunftzentrum.de 70 i+ for (c = chl; c < &chl[nch]; ++c) Err vernunftzentrum.de 70 i+ if (c->join) Err vernunftzentrum.de 70 i+ sndf("JOIN %s", c->name); Err vernunftzentrum.de 70 i+ reconn = 0; Err vernunftzentrum.de 70 i+ } Err vernunftzentrum.de 70 i if (FD_ISSET(srv.fd, &rfs)) { Err vernunftzentrum.de 70 i- if (!srd()) Err vernunftzentrum.de 70 i- quit = 1; Err vernunftzentrum.de 70 i+ if (!srd()) { Err vernunftzentrum.de 70 i+ reconn = 1; Err vernunftzentrum.de 70 i+ continue; Err vernunftzentrum.de 70 i+ } Err vernunftzentrum.de 70 i } Err vernunftzentrum.de 70 i if (FD_ISSET(srv.fd, &wfs)) { Err vernunftzentrum.de 70 i int wr; Err vernunftzentrum.de 70 i@@ -853,13 +904,10 @@ main(int argc, char *argv[]) Err vernunftzentrum.de 70 i wr = SSL_write(srv.ssl, outb, outp - outb); Err vernunftzentrum.de 70 i else Err vernunftzentrum.de 70 i wr = write(srv.fd, outb, outp - outb); Err vernunftzentrum.de 70 i- if (wr < 0) { Err vernunftzentrum.de 70 i- if (errno == EINTR) Err vernunftzentrum.de 70 i- continue; Err vernunftzentrum.de 70 i- panic("Write error."); Err vernunftzentrum.de 70 i- } Err vernunftzentrum.de 70 i- if (wr == 0) Err vernunftzentrum.de 70 i+ if (wr <= 0) { Err vernunftzentrum.de 70 i+ reconn = wr < 0; Err vernunftzentrum.de 70 i continue; Err vernunftzentrum.de 70 i+ } Err vernunftzentrum.de 70 i outp -= wr; Err vernunftzentrum.de 70 i memmove(outb, outb + wr, outp - outb); Err vernunftzentrum.de 70 i } Err vernunftzentrum.de 70 i@@ -867,14 +915,9 @@ main(int argc, char *argv[]) Err vernunftzentrum.de 70 i tgetch(); Err vernunftzentrum.de 70 i wrefresh(scr.iw); Err vernunftzentrum.de 70 i } Err vernunftzentrum.de 70 i+ continue; Err vernunftzentrum.de 70 i } Err vernunftzentrum.de 70 i- if (ssl) { Err vernunftzentrum.de 70 i- SSL_shutdown(srv.ssl); Err vernunftzentrum.de 70 i- SSL_free(srv.ssl); Err vernunftzentrum.de 70 i- close(srv.fd); Err vernunftzentrum.de 70 i- SSL_CTX_free(srv.ctx); Err vernunftzentrum.de 70 i- } else Err vernunftzentrum.de 70 i- close(srv.fd); Err vernunftzentrum.de 70 i+ hangup(); Err vernunftzentrum.de 70 i while (nch--) Err vernunftzentrum.de 70 i free(chl[nch].buf); Err vernunftzentrum.de 70 i treset(); Err vernunftzentrum.de 70 .