tRetry cleartext connection in case TLS failed - sacc - sacc (saccomys): simple gopher client.
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit 7e0793d8395184b5b21ecdd0b13bccb524d1e414
 (DIR) parent 4aa1ecfaf6c97cb02c7e34c88cc67c070b600b67
 (HTM) Author: Quentin Rameau <quinq@fifth.space>
       Date:   Sun, 11 Apr 2021 17:12:00 +0200
       
       Retry cleartext connection in case TLS failed
       
       Diffstat:
         M io_tls.c                            |      33 ++++++++++++++++++++++++++-----
         M sacc.c                              |      32 ++++++++++++++++---------------
       
       2 files changed, 45 insertions(+), 20 deletions(-)
       ---
 (DIR) diff --git a/io_tls.c b/io_tls.c
       t@@ -1,3 +1,4 @@
       +#include <stdlib.h>
        #include <string.h>
        #include <unistd.h>
        #include <netdb.h>
       t@@ -32,6 +33,7 @@ static int
        connect_tls(struct cnx *c, struct addrinfo *ai, const char *host)
        {
                struct tls *t;
       +        char *r;
                int s;
        
                c->tls = NULL;
       t@@ -43,13 +45,34 @@ connect_tls(struct cnx *c, struct addrinfo *ai, const char *host)
                if (tls) {
                        if ((t = tls_client()) == NULL)
                                return -1;
       -                if (tls_connect_socket(t, s, host) == -1)
       -                        return -1;
       -
       -                c->tls = t;
       +                if (tls_connect_socket(t, s, host) == 0) {
       +                        do {
       +                                s = tls_handshake(t);
       +                        } while (s == TLS_WANT_POLLIN || s == TLS_WANT_POLLOUT);
       +                        if (s == 0) {
       +                                c->tls = t;
       +                        } else {
       +                                diag("Can't establish TLS with \"%s\": %s",
       +                                     host, tls_error(t));
       +                                r = uiprompt("Retry on cleartext? [Yn]: ");
       +                                switch (*r) {
       +                                case 'Y':
       +                                case 'y':
       +                                case '\0':
       +                                        tls = 0;
       +                                        s = -2;
       +                                        break;
       +                                default:
       +                                        s = -3;
       +                                }
       +                                free(r);
       +                        }
       +                } else {
       +                        s = -1;
       +                }
                }
        
       -        return 0;
       +        return s;
        }
        
        static void
 (DIR) diff --git a/sacc.c b/sacc.c
       t@@ -491,8 +491,8 @@ connectto(const char *host, const char *port, struct cnx *c)
                    .ai_socktype = SOCK_STREAM,
                    .ai_protocol = IPPROTO_TCP,
                };
       -        struct addrinfo *addrs, *addr;
       -        int r, err;
       +        struct addrinfo *addrs, *ai;
       +        int r, err, conn;
        
                sigemptyset(&set);
                sigaddset(&set, SIGWINCH);
       t@@ -505,18 +505,20 @@ connectto(const char *host, const char *port, struct cnx *c)
                }
        
                r = -1;
       -        for (addr = addrs; addr; addr = addr->ai_next) {
       -                if ((c->sock = socket(addr->ai_family, addr->ai_socktype,
       -                                      addr->ai_protocol)) == -1) {
       -                        err = errno;
       -                        continue;
       -                }
       -
       -                if ((r = ioconnect(c, addr, host)) == 0)
       -                        break;
       +        for (ai = addrs; ai && r == -1; ai = ai->ai_next) {
       +                do {
       +                        if ((c->sock = socket(ai->ai_family, ai->ai_socktype,
       +                                              ai->ai_protocol)) == -1) {
       +                                err = errno;
       +                                break;
       +                        }
        
       -                err = errno;
       -                close(c->sock);
       +                        if ((r = ioconnect(c, ai, host)) < 0) {
       +                                err = errno;
       +                                ioclose(c);
       +                        }
       +                /* retry on cleartext */
       +                } while (r == -2);
                }
        
                freeaddrinfo(addrs);
       t@@ -537,7 +539,7 @@ download(Item *item, int dest)
                ssize_t r, w;
        
                if (item->tag == NULL) {
       -                if (connectto(item->host, item->port, &c) == -1 ||
       +                if (connectto(item->host, item->port, &c) < 0 ||
                            sendselector(&c, item->selector) == -1)
                                return 0;
                } else {
       t@@ -621,7 +623,7 @@ fetchitem(Item *item)
                struct cnx c;
                char *raw;
        
       -        if (connectto(item->host, item->port, &c) == -1 ||
       +        if (connectto(item->host, item->port, &c) < 0 ||
                    sendselector(&c, item->selector) == -1)
                        return 0;