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:
M | http.c | | | 103 | +++++++++++++++++++++++++++++++++++++++++++++++-------------------------------- |
M | http.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";