From 09b708f572d76de8db7f7948ea7359b19bbd1c5a Mon Sep 17 00:00:00 2001 From: claudio Date: Thu, 25 Mar 2021 12:18:45 +0000 Subject: [PATCH] Adjust HTTP client code a bit. Add support for 304 Not Modified responses, remove handling of 206 Partial Content (the client does not use range headers). Report the Last-Modified timestamp back to the requestor and switch OK to a enum value for (FAIL, OK and NOT MODIFIED). OK tb@ --- usr.sbin/rpki-client/extern.h | 8 +++++++- usr.sbin/rpki-client/http.c | 32 +++++++++++++++++--------------- usr.sbin/rpki-client/main.c | 29 +++++++++++++++-------------- 3 files changed, 39 insertions(+), 30 deletions(-) diff --git a/usr.sbin/rpki-client/extern.h b/usr.sbin/rpki-client/extern.h index 0fa14e1a383..03f6d8967cb 100644 --- a/usr.sbin/rpki-client/extern.h +++ b/usr.sbin/rpki-client/extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: extern.h,v 1.55 2021/03/19 13:56:10 claudio Exp $ */ +/* $OpenBSD: extern.h,v 1.56 2021/03/25 12:18:45 claudio Exp $ */ /* * Copyright (c) 2019 Kristaps Dzonsons * @@ -264,6 +264,12 @@ enum rtype { RTYPE_GBR, }; +enum http_result { + HTTP_FAILED, /* anything else */ + HTTP_OK, /* 200 OK */ + HTTP_NOT_MOD, /* 304 Not Modified */ +}; + /* * An entity (MFT, ROA, certificate, etc.) that needs to be downloaded * and parsed. diff --git a/usr.sbin/rpki-client/http.c b/usr.sbin/rpki-client/http.c index 84c11fac3da..8f49b745946 100644 --- a/usr.sbin/rpki-client/http.c +++ b/usr.sbin/rpki-client/http.c @@ -1,4 +1,4 @@ -/* $OpenBSD: http.c,v 1.8 2021/03/18 16:15:19 tb Exp $ */ +/* $OpenBSD: http.c,v 1.9 2021/03/25 12:18:45 claudio Exp $ */ /* * Copyright (c) 2020 Nils Fisher * Copyright (c) 2020 Claudio Jeker @@ -264,7 +264,7 @@ http_resolv(struct http_connection *conn, const char *host, const char *port) } static void -http_done(struct http_connection *conn, int ok) +http_done(struct http_connection *conn, enum http_result res) { struct ibuf *b; @@ -273,10 +273,8 @@ http_done(struct http_connection *conn, int ok) if ((b = ibuf_dynamic(64, UINT_MAX)) == NULL) err(1, NULL); io_simple_buffer(b, &conn->id, sizeof(conn->id)); - io_simple_buffer(b, &ok, sizeof(ok)); -#if 0 /* TODO: cache last_modified */ + io_simple_buffer(b, &res, sizeof(res)); io_str_buffer(b, conn->last_modified); -#endif ibuf_close(&msgq, b); } @@ -284,12 +282,13 @@ static void http_fail(size_t id) { struct ibuf *b; - int ok = 0; + enum http_result res = HTTP_FAILED; if ((b = ibuf_dynamic(8, UINT_MAX)) == NULL) err(1, NULL); io_simple_buffer(b, &id, sizeof(id)); - io_simple_buffer(b, &ok, sizeof(ok)); + io_simple_buffer(b, &res, sizeof(res)); + io_str_buffer(b, NULL); ibuf_close(&msgq, b); } @@ -434,7 +433,7 @@ http_redirect(struct http_connection *conn, char *uri) { char *host, *port, *path; - warnx("redirect to %s", http_info(uri)); + logx("redirect to %s", http_info(uri)); if (http_parse_uri(uri, &host, &port, &path) == -1) { free(uri); @@ -705,6 +704,7 @@ http_parse_status(struct http_connection *conn, char *buf) case 302: case 303: case 307: + case 308: if (conn->redirect_loop++ > 10) { warnx("%s: Too many redirections requested", http_info(conn->url)); @@ -712,7 +712,6 @@ http_parse_status(struct http_connection *conn, char *buf) } /* FALLTHROUGH */ case 200: - case 206: case 304: conn->status = status; break; @@ -729,7 +728,7 @@ static inline int http_isredirect(struct http_connection *conn) { if ((conn->status >= 301 && conn->status <= 303) || - conn->status == 307) + conn->status == 307 || conn->status == 308) return 1; return 0; } @@ -865,7 +864,7 @@ http_parse_chunked(struct http_connection *conn, char *buf) conn->chunksz = chunksize; if (conn->chunksz == 0) { - http_done(conn, 1); + http_done(conn, HTTP_OK); return 0; } @@ -970,7 +969,7 @@ data_write(struct http_connection *conn) memmove(conn->buf, conn->buf + s, conn->bufpos); if (conn->bytes == conn->filesize) { - http_done(conn, 1); + http_done(conn, HTTP_OK); return 0; } @@ -1065,10 +1064,13 @@ http_nextstep(struct http_connection *conn) conn->state = STATE_RESPONSE_HEADER; return WANT_POLLIN; case STATE_RESPONSE_HEADER: - if (conn->status == 200) + if (conn->status == 200) { conn->state = STATE_RESPONSE_DATA; - else { - http_done(conn, 0); + } else { + if (conn->status == 304) + http_done(conn, HTTP_NOT_MOD); + else + http_done(conn, HTTP_FAILED); return http_close(conn); } return WANT_POLLIN; diff --git a/usr.sbin/rpki-client/main.c b/usr.sbin/rpki-client/main.c index e922b7fe49d..70b7c6526aa 100644 --- a/usr.sbin/rpki-client/main.c +++ b/usr.sbin/rpki-client/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.122 2021/03/19 13:56:10 claudio Exp $ */ +/* $OpenBSD: main.c,v 1.123 2021/03/25 12:18:45 claudio Exp $ */ /* * Copyright (c) 2019 Kristaps Dzonsons * @@ -321,11 +321,11 @@ http_ta_fetch(struct repo *rp) } static int -http_done(struct repo *rp, int ok) +http_done(struct repo *rp, enum http_result res) { if (rp->repouri == NULL) { /* Move downloaded TA file into place, or unlink on failure. */ - if (ok) { + if (res == HTTP_OK) { char *file; file = ta_filename(rp, 0); @@ -339,18 +339,16 @@ http_done(struct repo *rp, int ok) rp->temp = NULL; } - if (!ok && rp->uriidx < REPO_MAX_URI - 1 && + if (res == HTTP_OK) + logx("%s: loaded from network", rp->local); + else if (rp->uriidx < REPO_MAX_URI - 1 && rp->uris[rp->uriidx + 1] != NULL) { logx("%s: load from network failed, retry", rp->local); rp->uriidx++; repo_fetch(rp); return 0; - } - - if (ok) - logx("%s: loaded from network", rp->local); - else + } else logx("%s: load from network failed, " "fallback to cache", rp->local); @@ -842,7 +840,7 @@ suicide(int sig __attribute__((unused))) int main(int argc, char *argv[]) { - int rc = 1, c, st, proc, rsync, http, + int rc = 1, c, st, proc, rsync, http, ok, fl = SOCK_STREAM | SOCK_CLOEXEC; size_t i, id, outsz = 0, talsz = 0; pid_t procpid, rsyncpid, httppid; @@ -1157,7 +1155,6 @@ main(int argc, char *argv[]) */ if ((pfd[0].revents & POLLIN)) { - int ok; io_simple_read(rsync, &id, sizeof(id)); io_simple_read(rsync, &ok, sizeof(ok)); rp = repo_find(id); @@ -1176,19 +1173,23 @@ main(int argc, char *argv[]) } if ((pfd[2].revents & POLLIN)) { - int ok; + enum http_result res; + char *last_mod; + io_simple_read(http, &id, sizeof(id)); - io_simple_read(http, &ok, sizeof(ok)); + io_simple_read(http, &res, sizeof(res)); + io_str_read(http, &last_mod); rp = repo_find(id); if (rp == NULL) errx(1, "unknown repository id: %zu", id); assert(!rp->loaded); - if (http_done(rp, ok)) { + if (http_done(rp, res)) { rp->loaded = 1; stats.repos++; entityq_flush(rp); } + free(last_mod); } /* -- 2.20.1