wdvi

network DVI viewer
Log | Files | Refs

commit e5ebcb757186de5f37aafe2edaa2c307d51cdfac
parent 7eb039cfdfb21c74b51e97db80ffe45b1bd703a6
Author: Kyle Milz <krwmilz@gmail.com>
Date:   Tue,  7 Sep 2021 16:43:35 +0000

two improvements for network code

First, use getaddrinfo() instead of gethostent() for DNS resolving as
it seems to work better, and i think we pick up IPv6 support for free.

Second, support DVI fetches larger than 16kb, the default openssl record
size.

Diffstat:
Mhttp.c | 103+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Mhttp.h | 2+-
2 files changed, 62 insertions(+), 43 deletions(-)

diff --git a/http.c b/http.c @@ -14,15 +14,13 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <sys/types.h> #include <sys/socket.h> /* connect(), socket() */ -#include <arpa/inet.h> /* inet_ntoa() */ -#include <netdb.h> /* gethostbyname() */ -#include <netinet/in.h> /* struct sockaddr_in */ +#include <netdb.h> /* getaddrinfo() */ #include <assert.h> #include <err.h> /* err() */ -#include <stdio.h> /* sscanf, fmemopen */ #include <stdlib.h> /* strtonum() */ #include <unistd.h> /* close() */ @@ -123,7 +121,8 @@ parse_url(const char dest_url[]) /* * Takes a struct url and resolves the url hostname. Then tries connecting to - * the url hostname using the url port. + * the url hostname using "https" service port. This should be modified to + * use url->port. * * On success return an open socket represented by a non negative integer or * -1 on failure. @@ -131,34 +130,45 @@ parse_url(const char dest_url[]) static int xconnect(struct url *url) { - struct hostent *host; - int sockfd; - struct sockaddr_in dest_addr; - - if ((host = gethostbyname(url->hostname)) == NULL) { - warning_popup_long("%s: %s", "OK", NULL, url->hostname, - hstrerror(h_errno)); - return -1; - } - - if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) - err(1, "socket"); - - dest_addr.sin_family = AF_INET; - dest_addr.sin_port = htons(url->port); - dest_addr.sin_addr.s_addr = *(long *)(host->h_addr); + struct addrinfo hints, *res, *res0; + int error; + int save_errno; + int s; + const char *cause = NULL; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + error = getaddrinfo(url->hostname, "https", &hints, &res0); + if (error) + errx(1, "%s", gai_strerror(error)); + + s = -1; + for (res = res0; res; res = res->ai_next) { + s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (s == -1) { + cause = "socket"; + continue; + } - memset(&(dest_addr.sin_zero), '\0', 8); + if (connect(s, res->ai_addr, res->ai_addrlen) == -1) { + cause = "connect"; + save_errno = errno; + close(s); + errno = save_errno; + s = -1; + continue; + } - if (connect(sockfd, (struct sockaddr *) &dest_addr, - sizeof(struct sockaddr)) == -1) { - warning_popup_long("%s:%i: %s", "OK", NULL, - url->hostname, url->port, strerror(errno)); - close(sockfd); - return -1; + /* connect() succeeded */ + break; } + if (s == -1) + err(1, "%s", cause); + freeaddrinfo(res0); - return sockfd; + return s; } @@ -349,7 +359,8 @@ read_response(SSL *tls, struct url *url) { char *buf; struct http_headers *response; - int nbytes; + int nbytes = 0; + int total_bytes = 0; FILE *dvi_file = NULL; /* This buffer must be null terminated. */ @@ -371,26 +382,34 @@ read_response(SSL *tls, struct url *url) goto free_response; } - /* Second (or more) reads are the HTTP body response. */ - if ((nbytes = SSL_read(tls, buf, SSL_BUF_SIZE)) < 1) { - warning_popup_long("SSL_read: %s: %s", "OK", NULL, - url->hostname, SSL_strerror(tls, nbytes)); - goto free_response; - } - /* XDvi does all it's processing with FILE streams. */ - if ((dvi_file = fmemopen(NULL, nbytes, "r+")) == NULL) + if ((dvi_file = fmemopen(NULL, response->content_len, "r+")) == NULL) err(1, "fmemopen"); - if (fwrite(buf, 1, nbytes, dvi_file) < nbytes) - err(1, "fwrite"); + /* Second (or more) reads are the HTTP body response. */ + while (total_bytes < response->content_len) { + nbytes = SSL_read(tls, buf, SSL_BUF_SIZE); + + if (nbytes < 1) { + warning_popup_long("SSL_read: %s: %s", "OK", NULL, + url->hostname, SSL_strerror(tls, nbytes)); + fclose(dvi_file); + dvi_file = NULL; + goto free_response; + } + + if (fwrite(buf, 1, nbytes, dvi_file) < nbytes) + err(1, "fwrite"); + + total_bytes += nbytes; + } if (fseek(dvi_file, 0L, SEEK_SET) < 0) err(1, "fseek"); - printf("Number of HTTP body bytes: %i\n", nbytes); + printf("Number of HTTP body bytes: %i\n", total_bytes); - if (nbytes != response->content_len) + if (total_bytes != response->content_len) warning_popup_long("HTTP body len: expected %i but read %i\n", "OK", NULL, response->content_len, nbytes); diff --git a/http.h b/http.h @@ -1,4 +1,4 @@ -#include <stdio.h> /* FILE, fseek(), fwrite(), tmpfile() */ +#include <stdio.h> /* FILE, fseek(), fwrite() */ static const char addr_default[] = "www.0x30.net/resume.dvi";