On Thu, Mar 25, 2021 at 10:46:18AM +0100, Claudio Jeker wrote:
> This diff is mostly cleanup and adding the missing bits needed for RRDP.
> Instead of a simple bool ok use an enum to report the state back.
> Can be fail, ok or not-modified (the last is used for 304 Not Modified
> answers (if a If-Modified-Since header was passed in the request).
>
> Additionally add 308 redirect support and remove 206 as a valid status
> response. The http client does not do range requests so a 206 return is
> never expected.
ok tb
>
> --
> :wq Claudio
>
> Index: extern.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
> retrieving revision 1.55
> diff -u -p -r1.55 extern.h
> --- extern.h 19 Mar 2021 13:56:10 -0000 1.55
> +++ extern.h 25 Mar 2021 09:10:04 -0000
> @@ -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.
> Index: http.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/http.c,v
> retrieving revision 1.8
> diff -u -p -r1.8 http.c
> --- http.c 18 Mar 2021 16:15:19 -0000 1.8
> +++ http.c 25 Mar 2021 09:12:18 -0000
> @@ -264,7 +264,7 @@ http_resolv(struct http_connection *conn
> }
>
> 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,
> 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 *co
> {
> 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
> 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
> }
> /* 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_connectio
> 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 *co
> 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;
> Index: main.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
> retrieving revision 1.122
> diff -u -p -r1.122 main.c
> --- main.c 19 Mar 2021 13:56:10 -0000 1.122
> +++ main.c 25 Mar 2021 09:15:22 -0000
> @@ -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);
> }
>
> /*
>