]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Add several values to uri_type
authorAlberto Leiva Popper <ydahhrk@gmail.com>
Fri, 1 Mar 2024 21:25:54 +0000 (15:25 -0600)
committerAlberto Leiva Popper <ydahhrk@gmail.com>
Fri, 1 Mar 2024 22:07:31 +0000 (16:07 -0600)
In the upcoming commits, the cache is going to need to start managing
the notifications differently from the other downloadables, including
snapshots and deltas.

The logic used to differentiate the different objects from each other
was getting convoluted, and had been naturally converging into the URI
object since the 1.6.0 refactors, IIRC.

So stop beating around the bush and commit to this design. Store the
type in the URI object, and add several values to the uri_type enum.

21 files changed:
src/cache/local_cache.c
src/cache/local_cache.h
src/common.c
src/file.c
src/file.h
src/http/http.c
src/http/http.h
src/init.c
src/json_util.c
src/json_util.h
src/object/certificate.c
src/object/manifest.c
src/object/tal.c
src/rrdp.c
src/types/uri.c
src/types/uri.h
test/cache/local_cache_test.c
test/crypto/hash_test.c
test/rrdp_test.c
test/tal_test.c
test/types/uri_test.c

index 4550ecb6a965a926b19481ef85c64dcbe32e6189..3f431d676e5d890ccdf6c74a69600ea54b76a26d 100644 (file)
@@ -49,11 +49,16 @@ struct rpki_cache {
 #define TMPDIR "tmp"
 
 #define TAL_METAFILE "tal.json"
+#define TAGNAME_TYPE "type"
 #define TAGNAME_URL "url"
 #define TAGNAME_ATTEMPT_TS "attempt-timestamp"
 #define TAGNAME_ATTEMPT_ERR "attempt-result"
 #define TAGNAME_SUCCESS_TS "success-timestamp"
-#define TAGNAME_IS_NOTIF "is-rrdp-notification"
+
+#define TYPEVALUE_TA_RSYNC "TA (rsync)"
+#define TYPEVALUE_TA_HTTP "TA (HTTP)"
+#define TYPEVALUE_RPP "RPP"
+#define TYPEVALUE_NOTIF "RRDP Notification"
 
 static atomic_uint file_counter;
 
@@ -243,34 +248,41 @@ static struct cache_node *
 json2node(struct rpki_cache *cache, json_t *json)
 {
        struct cache_node *node;
-       char const *url;
-       bool is_notif;
+       char const *type_str;
        enum uri_type type;
+       char const *url;
        int error;
 
        node = pzalloc(sizeof(struct cache_node));
 
-       error = json_get_str(json, TAGNAME_URL, &url);
+       error = json_get_str(json, TAGNAME_TYPE, &type_str);
        if (error) {
                if (error > 0)
-                       pr_op_err("Node is missing the '" TAGNAME_URL "' tag.");
+                       pr_op_err("Node is missing the '" TAGNAME_TYPE "' tag.");
                goto fail;
        }
 
-       if (str_starts_with(url, "https://"))
-               type = UT_HTTPS;
-       else if (str_starts_with(url, "rsync://"))
-               type = UT_RSYNC;
+       if (strcmp(type_str, TYPEVALUE_TA_RSYNC) == 0)
+               type = UT_TA_RSYNC;
+       else if (strcmp(type_str, TYPEVALUE_TA_HTTP) == 0)
+               type = UT_TA_HTTP;
+       else if (strcmp(type_str, TYPEVALUE_RPP) == 0)
+               type = UT_RPP;
+       else if (strcmp(type_str, TYPEVALUE_NOTIF) == 0)
+               type = UT_NOTIF;
        else {
-               pr_op_err("Unknown protocol: %s", url);
+               pr_op_err("Unknown node type: %s", type_str);
                goto fail;
        }
 
-       error = json_get_bool(json, TAGNAME_IS_NOTIF, &is_notif);
-       if (error < 0)
+       error = json_get_str(json, TAGNAME_URL, &url);
+       if (error) {
+               if (error > 0)
+                       pr_op_err("Node is missing the '" TAGNAME_URL "' tag.");
                goto fail;
+       }
 
-       error = uri_create(&node->url, cache->tal, type, is_notif, NULL, url);
+       error = uri_create(&node->url, cache->tal, type, NULL, url);
        if (error) {
                pr_op_err("Cannot parse '%s' into a URI.", url);
                goto fail;
@@ -302,11 +314,10 @@ fail:
 }
 
 static struct cache_node*
-find_node(struct rpki_cache *cache, struct rpki_uri *uri)
+find_node(struct rpki_cache *cache, char const *luri)
 {
-       char const *key = uri_get_local(uri);
        struct cache_node *result;
-       HASH_FIND_STR(cache->ht, key, result);
+       HASH_FIND_STR(cache->ht, luri, result);
        return result;
 }
 
@@ -380,18 +391,33 @@ static json_t *
 node2json(struct cache_node *node)
 {
        json_t *json;
+       char const *type;
 
        json = json_object();
-       if (json == NULL) {
-               pr_op_err("json object allocation failure.");
-               return NULL;
+       if (json == NULL)
+               enomem_panic();
+
+       switch (uri_get_type(node->url)) {
+       case UT_TA_RSYNC:
+               type = TYPEVALUE_TA_RSYNC;
+               break;
+       case UT_TA_HTTP:
+               type = TYPEVALUE_TA_HTTP;
+               break;
+       case UT_RPP:
+               type = TYPEVALUE_RPP;
+               break;
+       case UT_NOTIF:
+               type = TYPEVALUE_NOTIF;
+               break;
+       default:
+               goto cancel;
        }
 
+       if (json_add_str(json, TAGNAME_TYPE, type))
+               goto cancel;
        if (json_add_str(json, TAGNAME_URL, uri_get_global(node->url)))
                goto cancel;
-       if (uri_is_notif(node->url))
-               if (json_add_bool(json, TAGNAME_IS_NOTIF, true))
-                       goto cancel;
        if (json_add_date(json, TAGNAME_ATTEMPT_TS, node->attempt.ts))
                goto cancel;
        if (json_add_int(json, TAGNAME_ATTEMPT_ERR, node->attempt.result))
@@ -460,7 +486,7 @@ get_url(struct rpki_uri *uri, const char *tal, struct rpki_uri **url)
        unsigned int slashes;
        int error;
 
-       if (uri_get_type(uri) != UT_RSYNC) {
+       if (uri_get_type(uri) != UT_RPP) {
                uri_refget(uri);
                *url = uri;
                return 0;
@@ -516,7 +542,7 @@ get_url(struct rpki_uri *uri, const char *tal, struct rpki_uri **url)
                if (*c == '/') {
                        slashes++;
                        if (slashes == 4)
-                               return __uri_create(url, tal, UT_RSYNC, false,
+                               return __uri_create(url, tal, UT_RPP,
                                    NULL, guri, c - guri + 1);
                }
        }
@@ -524,7 +550,7 @@ get_url(struct rpki_uri *uri, const char *tal, struct rpki_uri **url)
        if (slashes == 3 && *(c - 1) != '/') {
                guri2 = pstrdup(guri); /* Remove const */
                guri2[c - guri] = '/';
-               error = __uri_create(url, tal, UT_RSYNC, false, NULL, guri2,
+               error = __uri_create(url, tal, UT_RPP, NULL, guri2,
                    c - guri + 1);
                free(guri2);
                return error;
@@ -566,10 +592,11 @@ cache_check(struct rpki_uri *url)
 }
 
 /**
- * @changed only on HTTP.
+ * @ims and @changed only on HTTP.
  */
 int
-cache_download(struct rpki_cache *cache, struct rpki_uri *uri, bool *changed)
+cache_download(struct rpki_cache *cache, struct rpki_uri *uri,
+    curl_off_t ims, bool *changed)
 {
        struct rpki_uri *url;
        struct cache_node *node;
@@ -582,7 +609,7 @@ cache_download(struct rpki_cache *cache, struct rpki_uri *uri, bool *changed)
        if (error)
                return error;
 
-       node = find_node(cache, url);
+       node = find_node(cache, uri_get_local(url));
        if (node != NULL) {
                uri_refput(url);
                if (was_recently_downloaded(cache, node))
@@ -595,18 +622,21 @@ cache_download(struct rpki_cache *cache, struct rpki_uri *uri, bool *changed)
        }
 
        switch (uri_get_type(url)) {
-       case UT_RSYNC:
+       case UT_TA_HTTP:
+       case UT_NOTIF:
+       case UT_TMP:
+               error = config_get_http_enabled()
+                  ? http_download(url, ims, changed)
+                  : cache_check(url);
+               break;
+       case UT_TA_RSYNC:
+       case UT_RPP:
                error = config_get_rsync_enabled()
                    ? rsync_download(url)
                    : cache_check(url);
                break;
-       case UT_HTTPS:
-               error = config_get_http_enabled()
-                   ? http_download(url, changed)
-                   : cache_check(url);
-               break;
        default:
-               pr_crit("Unexpected URI type: %d", uri_get_type(url));
+               pr_crit("URI type not downloadable: %d", uri_get_type(url));
        }
 
        node->attempt.ts = time(NULL);
@@ -622,32 +652,43 @@ cache_download(struct rpki_cache *cache, struct rpki_uri *uri, bool *changed)
 }
 
 static int
-download(struct rpki_cache *cache, struct rpki_uri *uri, bool use_rrdp,
-    uris_dl_cb cb, void *arg)
+download(struct rpki_cache *cache, struct rpki_uri *uri, uris_dl_cb cb, void *arg)
 {
+       time_t ims = 0;
        int error;
 
        pr_val_debug("Trying URL %s...", uri_get_global(uri));
 
-       error = (use_rrdp && (uri_get_type(uri) == UT_HTTPS))
-           ? rrdp_update(uri)
-           : cache_download(cache, uri, NULL);
-       if (error)
-               return 1;
+       switch (uri_get_type(uri)) {
+       case UT_TA_HTTP:
+               error = file_get_mtim(uri_get_local(uri), &ims);
+               if (error)
+                       break;
+               /* Fall through */
+       case UT_TA_RSYNC:
+       case UT_RPP:
+               error = cache_download(cache, uri, ims, NULL);
+               break;
+       case UT_NOTIF:
+               error = rrdp_update(uri);
+               break;
+       default:
+               pr_crit("URI type is not a legal alt candidate: %u", uri_get_type(uri));
+       }
 
-       return cb(uri, arg);
+       return error ? 1 : cb(uri, arg);
 }
 
 static int
 download_uris(struct rpki_cache *cache, struct uri_list *uris,
-    enum uri_type type, bool use_rrdp, uris_dl_cb cb, void *arg)
+    enum uri_type type, uris_dl_cb cb, void *arg)
 {
        struct rpki_uri **uri;
        int error;
 
        ARRAYLIST_FOREACH(uris, uri) {
                if (uri_get_type(*uri) == type) {
-                       error = download(cache, *uri, use_rrdp, cb, arg);
+                       error = download(cache, *uri, cb, arg);
                        if (error <= 0)
                                return error;
                }
@@ -670,36 +711,36 @@ download_uris(struct rpki_cache *cache, struct uri_list *uris,
  */
 int
 cache_download_alt(struct rpki_cache *cache, struct uri_list *uris,
-    bool use_rrdp, uris_dl_cb cb, void *arg)
+    enum uri_type http_type, enum uri_type rsync_type, uris_dl_cb cb, void *arg)
 {
        struct rpki_uri **cursor, *uri;
        int error;
 
        if (config_get_http_priority() > config_get_rsync_priority()) {
-               error = download_uris(cache, uris, UT_HTTPS, use_rrdp, cb, arg);
+               error = download_uris(cache, uris, http_type, cb, arg);
                if (error <= 0)
                        return error;
-               error = download_uris(cache, uris, UT_RSYNC, use_rrdp, cb, arg);
+               error = download_uris(cache, uris, rsync_type, cb, arg);
                if (error <= 0)
                        return error;
 
        } else if (config_get_http_priority() < config_get_rsync_priority()) {
-               error = download_uris(cache, uris, UT_RSYNC, use_rrdp, cb, arg);
+               error = download_uris(cache, uris, rsync_type, cb, arg);
                if (error <= 0)
                        return error;
-               error = download_uris(cache, uris, UT_HTTPS, use_rrdp, cb, arg);
+               error = download_uris(cache, uris, http_type, cb, arg);
                if (error <= 0)
                        return error;
 
        } else {
                ARRAYLIST_FOREACH(uris, cursor) {
-                       error = download(cache, *cursor, use_rrdp, cb, arg);
+                       error = download(cache, *cursor, cb, arg);
                        if (error <= 0)
                                return error;
                }
        }
 
-       uri = cache_recover(cache, uris, use_rrdp);
+       uri = cache_recover(cache, uris);
        return (uri != NULL) ? cb(uri, arg) : ESRCH;
 }
 
@@ -743,7 +784,7 @@ struct uri_and_node {
 
 /* Separated because of unit tests. */
 static void
-__cache_recover(struct rpki_cache *cache, struct uri_list *uris, bool use_rrdp,
+__cache_recover(struct rpki_cache *cache, struct uri_list *uris,
     struct uri_and_node *best)
 {
        struct rpki_uri **uri;
@@ -755,7 +796,7 @@ __cache_recover(struct rpki_cache *cache, struct uri_list *uris, bool use_rrdp,
 
                if (get_url(cursor.uri, cache->tal, &url) != 0)
                        continue;
-               cursor.node = find_node(cache, url);
+               cursor.node = find_node(cache, uri_get_local(url));
                uri_refput(url);
                if (cursor.node == NULL)
                        continue;
@@ -766,10 +807,10 @@ __cache_recover(struct rpki_cache *cache, struct uri_list *uris, bool use_rrdp,
 }
 
 struct rpki_uri *
-cache_recover(struct rpki_cache *cache, struct uri_list *uris, bool use_rrdp)
+cache_recover(struct rpki_cache *cache, struct uri_list *uris)
 {
        struct uri_and_node best = { 0 };
-       __cache_recover(cache, uris, use_rrdp, &best);
+       __cache_recover(cache, uris, &best);
        return best.uri;
 }
 
@@ -806,7 +847,7 @@ delete_node_and_cage(struct rpki_cache *cache, struct cache_node *node)
 {
        struct rpki_uri *cage;
 
-       if (uri_is_notif(node->url)) {
+       if (uri_get_type(node->url) == UT_NOTIF) {
                if (uri_create_cage(&cage, cache->tal, node->url) == 0) {
                        pr_op_debug("Deleting cage %s.", uri_get_local(cage));
                        file_rm_rf(uri_get_local(cage));
@@ -840,6 +881,22 @@ get_days_ago(int days)
        return last_week;
 }
 
+static void
+cleanup_tmp(struct rpki_cache *cache, struct cache_node *node)
+{
+       char const *path;
+       int error;
+
+       if (uri_get_type(node->url) == UT_TMP) {
+               path = uri_get_local(node->url);
+               pr_op_debug("Deleting temporal file '%s'.", path);
+               error = file_rm_f(path);
+               if (error)
+                       pr_op_err("Could not delete '%s': %s", path, strerror(error));
+               delete_node(cache, node);
+       }
+}
+
 static void
 cleanup_node(struct rpki_cache *cache, struct cache_node *node,
     time_t last_week)
@@ -910,8 +967,11 @@ delete_if_unknown(const char *fpath, const struct stat *sb, int typeflag,
 {
        if (!is_cached(fpath)) {
                pr_op_debug("Deleting untracked file or directory %s.", fpath);
-               remove(fpath);
+               errno = 0;
+               if (remove(fpath) != 0)
+                       pr_op_err("Cannot delete '%s': %s", fpath, strerror(errno));
        }
+
        return 0;
 }
 
@@ -938,7 +998,7 @@ delete_unknown_files(struct rpki_cache *cache)
                uri_refget(node->url);
                uris_add(&dnc, node->url);
 
-               if (!uri_is_notif(node->url))
+               if (uri_get_type(node->url) != UT_NOTIF)
                        continue;
 
                if (uri_create_cage(&cage, cache->tal, node->url) != 0) {
@@ -971,6 +1031,10 @@ cache_cleanup(struct rpki_cache *cache)
        struct cache_node *node, *tmp;
        time_t last_week;
 
+       pr_op_debug("Cleaning up temporal files.");
+       HASH_ITER(hh, cache->ht, node, tmp)
+               cleanup_tmp(cache, node);
+
        pr_op_debug("Cleaning up old abandoned cache files.");
        last_week = get_days_ago(7);
        HASH_ITER(hh, cache->ht, node, tmp)
index 93eb11f1a2dcffc1a058d1f49c0fc4b97916e68e..1925351256d269700d8e19a1d3deb9bd5df0e746 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef SRC_CACHE_LOCAL_CACHE_H_
 #define SRC_CACHE_LOCAL_CACHE_H_
 
+#include <curl/curl.h>
 #include "types/uri.h"
 
 struct rpki_cache;
@@ -15,7 +16,7 @@ struct rpki_cache *cache_create(char const *);
 void cache_destroy(struct rpki_cache *);
 
 /* Downloads @uri into the cache */
-int cache_download(struct rpki_cache *, struct rpki_uri *uri, bool *);
+int cache_download(struct rpki_cache *, struct rpki_uri *uri, curl_off_t, bool *);
 
 /*
  * The callback should return
@@ -25,11 +26,11 @@ int cache_download(struct rpki_cache *, struct rpki_uri *uri, bool *);
  * - < 0 on hard errors ("Abandon foreach")
  */
 typedef int (*uris_dl_cb)(struct rpki_uri *, void *);
-int cache_download_alt(struct rpki_cache *, struct uri_list *, bool,
-    uris_dl_cb, void *);
+int cache_download_alt(struct rpki_cache *, struct uri_list *, enum uri_type,
+    enum uri_type, uris_dl_cb, void *);
 
 /* Returns the most recent successfully cached URI of the list */
-struct rpki_uri *cache_recover(struct rpki_cache *, struct uri_list *, bool);
+struct rpki_uri *cache_recover(struct rpki_cache *, struct uri_list *);
 /* Prints the cache in standard output. */
 void cache_print(struct rpki_cache *);
 
index a0e9ec012cf722c4659299daab873b8fd0a27d07..b73297a2a279195299d4dab24e9f4c8fc76de1eb 100644 (file)
@@ -238,9 +238,9 @@ dir_exists(char const *path)
        if (stat(path, &meta) != 0) {
                error = errno;
                if (error == ENOENT)
-                       return false;
+                       return 0;
                pr_op_err_st("stat() failed: %s", strerror(error));
-               return error;
+               return -error;
        }
 
        if (!S_ISDIR(meta.st_mode)) {
@@ -308,31 +308,13 @@ end:
        return result;
 }
 
-static int
-remove_file(char const *path)
-{
-       int error;
-
-       errno = 0;
-       if (remove(path) != 0) {
-               error = errno;
-               /*
-               pr_val_err("Couldn't delete '%s': %s", path,
-                   strerror(error));
-                */
-               return error;
-       }
-
-       return 0;
-}
-
 /*
- * Delete parent dirs of @path only if dirs are empty, @path must be a file
- * location and will be deleted first.
+ * Delete @path.
+ * If path's parent is now empty, delete parent as well.
+ * If parent's parent is now empty, delete parent's parent.
+ * And so on.
  *
- * The algorithm is a bit aggressive, but rmdir() won't delete
- * something unless is empty, so in case the dir still has something in
- * it the cycle is finished.
+ * FIXME this should be done by the cache cleaner instead.
  */
 int
 delete_dir_recursive_bottom_up(char const *path)
@@ -342,9 +324,12 @@ delete_dir_recursive_bottom_up(char const *path)
        size_t config_len;
        int error;
 
-       error = remove_file(path);
-       if (error)
+       errno = 0;
+       if (remove(path) != 0) {
+               error = errno;
+               pr_val_err("Couldn't delete '%s': %s", path, strerror(error));
                return error;
+       }
 
        config_repo = pstrdup(config_get_local_repository());
 
index ad8bbda99122febed133e49afea82884f21186f1..d3a64b1497bc9bda40da0ce8a5ae57c5c1b372bf 100644 (file)
@@ -154,10 +154,53 @@ file_valid(char const *file_name)
        return true;
 }
 
+int
+file_get_mtim(char const *file, time_t *ims)
+{
+       struct stat meta;
+       int error;
+
+       if (stat(file, &meta) != 0) {
+               error = errno;
+               /*
+                * This happens to be most convenient for callers,
+                * because they all want to convert the ims to a curl_off_t ATM.
+                */
+               *ims = 0;
+               return (error == ENOENT) ? 0 : error;
+       }
+
+#ifdef __APPLE__
+       *ims = meta.st_mtime; /* Seriously, Apple? */
+#else
+       *ims = meta.st_mtim.tv_sec;
+#endif
+       return 0;
+}
+
+/*
+ * Like remove(), but don't care if the file is already deleted.
+ */
+int
+file_rm_f(char const *path)
+{
+       int error;
+
+       errno = 0;
+       if (remove(path) != 0) {
+               error = errno;
+               if (error != ENOENT)
+                       return error;
+       }
+
+       return 0;
+}
+
 static int
 rm(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
 {
        pr_op_debug("Deleting %s.", fpath);
+       errno = 0;
        return (remove(fpath) != 0) ? errno : 0;
 }
 
index 67f95b06c0503033ab7f41f98541b9c6799d45b8..f62b00b6d4e822ef8ddfc6fecea12b4c2bcd986e 100644 (file)
@@ -32,7 +32,9 @@ void file_free(struct file_contents *);
 
 int file_exists(char const *);
 bool file_valid(char const *);
+int file_get_mtim(char const *, time_t *);
 
+int file_rm_f(char const *);
 int file_rm_rf(char const *);
 
 /*
index 53a681b789aed143cba3f35f2ba9c5cbc7c5e6e9..0de473bbea8949382691466ccd098c68f34ad6d6 100644 (file)
@@ -1,7 +1,5 @@
 #include "http/http.h"
 
-#include <curl/curl.h>
-
 #include "alloc.h"
 #include "common.h"
 #include "config.h"
@@ -33,26 +31,6 @@ http_cleanup(void)
        curl_global_cleanup();
 }
 
-static int
-get_ims(char const *file, time_t *ims)
-{
-       struct stat meta;
-       int error;
-
-       if (stat(file, &meta) != 0) {
-               error = errno;
-               *ims = 0;
-               return (error == ENOENT) ? 0 : error;
-       }
-
-#ifdef __APPLE__
-       *ims = meta.st_mtime; /* Seriously, Apple? */
-#else
-       *ims = meta.st_mtim.tv_sec;
-#endif
-       return 0;
-}
-
 static void
 setopt_str(CURL *curl, CURLoption opt, char const *value)
 {
@@ -345,30 +323,42 @@ http_fetch(char const *src, char const *dst, curl_off_t ims, bool *changed)
 
        pr_val_debug("HTTP result code: %ld", http_code);
        error = 0;
-       *changed = true;
+       if (changed != NULL)
+               *changed = true;
 
 end:   http_easy_cleanup(&handler);
        if (error)
-               remove(dst);
+               file_rm_f(dst);
        return error;
 }
 
 /*
- * Assumes @dst's parent directory has already been created.
+ * Download @uri->global into @uri->local; HTTP assumed.
+ *
+ * If @changed returns true, the file was downloaded normally.
+ * If @changed returns false, the file has not been modified since @ims.
+ *
+ * @ims can be 0, which means "no epoch."
+ * @changed can be NULL, which means "I don't care."
+ * If @changed is not NULL, initialize it to false.
  */
-static int
-do_retries(char const *src, char const *dst, curl_off_t ims, bool *changed)
+int
+http_download(struct rpki_uri *uri, curl_off_t ims, bool *changed)
 {
        unsigned int r;
        int error;
 
-       pr_val_debug("Downloading '%s'.", src);
+       pr_val_info("HTTP GET: %s -> %s", uri_get_global(uri), uri_get_local(uri));
 
-       r = 0;
-       do {
+       error = mkdir_p(uri_get_local(uri), false);
+       if (error)
+               return error;
+
+       for (r = 0; true; r++) {
                pr_val_debug("Download attempt #%u...", r + 1);
 
-               error = http_fetch(src, dst, ims, changed);
+               error = http_fetch(uri_get_global(uri), uri_get_local(uri),
+                   ims, changed);
                switch (error) {
                case 0:
                        pr_val_debug("Download successful.");
@@ -394,63 +384,7 @@ do_retries(char const *src, char const *dst, curl_off_t ims, bool *changed)
                 * down; use a thread pool.
                 */
                sleep(config_get_http_retry_interval());
-               r++;
-       } while (true);
-}
-
-/*
- * Download @uri->global into @uri->local; HTTP assumed.
- *
- * If @changed returns true, the file was downloaded normally.
- * If @changed returns false, the file already existed and is already its latest
- * version.
- * @changed can be NULL.
- */
-int
-http_download(struct rpki_uri *uri, bool *changed)
-{
-       char *tmp_file_name;
-       char const *final_file_name;
-       time_t ims;
-       bool __changed;
-       int error;
-
-       if (changed == NULL)
-               changed = &__changed;
-       *changed = false;
-
-       error = cache_tmpfile(&tmp_file_name);
-       if (error)
-               return error;
-       final_file_name = uri_get_local(uri);
-       error = get_ims(final_file_name, &ims);
-       if (error)
-               goto end;
-
-       pr_val_info("HTTP GET: %s -> %s", uri_get_global(uri), final_file_name);
-
-       error = do_retries(uri_get_global(uri), tmp_file_name, (curl_off_t)ims,
-           changed);
-       if (error || !(*changed))
-               goto end;
-
-       error = mkdir_p(final_file_name, false);
-       if (error) {
-               remove(tmp_file_name);
-               goto end;
        }
-
-       error = rename(tmp_file_name, final_file_name);
-       if (error) {
-               error = errno;
-               pr_val_err("Renaming temporal file from '%s' to '%s': %s",
-                   tmp_file_name, final_file_name, strerror(error));
-               remove(tmp_file_name);
-               goto end;
-       }
-
-end:   free(tmp_file_name);
-       return error;
 }
 
 /*
@@ -458,9 +392,8 @@ end:        free(tmp_file_name);
  * structure is created).
  */
 int
-http_direct_download(char const *remote, char const *dest)
+http_download_direct(char const *src, char const *dst)
 {
-       bool changed;
-       pr_val_info("HTTP GET: %s -> %s", remote, dest);
-       return http_fetch(remote, dest, 0, &changed);
+       pr_val_info("HTTP GET: %s -> %s", src, dst);
+       return http_fetch(src, dst, 0, NULL);
 }
index 41cb6692aa78eae872aec2cf20d8052805392eaa..2a446dc86a0caf815d1a3508c2d2f547d76c84c5 100644 (file)
@@ -1,12 +1,13 @@
 #ifndef SRC_HTTP_HTTP_H_
 #define SRC_HTTP_HTTP_H_
 
+#include <curl/curl.h>
 #include "types/uri.h"
 
 int http_init(void);
 void http_cleanup(void);
 
-int http_download(struct rpki_uri *, bool *);
-int http_direct_download(char const *, char const *);
+int http_download(struct rpki_uri *, curl_off_t, bool *);
+int http_download_direct(char const *, char const *);
 
 #endif /* SRC_HTTP_HTTP_H_ */
index 9018188291459da91e023a0cd1256168efe50301..4b444eeadfd5e84b6be1fc9fc8bc8bfbcac82b39 100644 (file)
@@ -47,7 +47,7 @@ fetch_url(char const *url)
        offset += strlen(dest_file);
        dest[offset] = '\0';
 
-       error = http_direct_download(url, dest);
+       error = http_download_direct(url, dest);
        if (error) {
                fprintf(stderr, "Couldn't fetch '%s'.\n", dest);
                free(dest);
index 870ecadd5b4354a33cad2f30f4be9ca418bb42ea..439caf6fdb925a8665a55553e2071079f801ebee 100644 (file)
@@ -29,24 +29,6 @@ json_get_str(json_t *parent, char const *name, char const **result)
        return 0;
 }
 
-int
-json_get_bool(json_t *parent, char const *name, bool *result)
-{
-       json_t *child;
-
-       *result = false;
-
-       child = json_object_get(parent, name);
-       if (child == NULL)
-               return ENOENT;
-
-       if (!json_is_boolean(child))
-               return pr_op_err("Tag '%s' is not a JSON boolean.", name);
-
-       *result = json_boolean_value(child);
-       return 0;
-}
-
 static int
 json_get_int_t(json_t *parent, char const *name, json_int_t *result)
 {
@@ -183,18 +165,6 @@ json_valid_members_count(json_t *object, size_t expected_size)
        return json_object_size(object) == expected_size;
 }
 
-int
-json_add_bool(json_t *parent, char const *name, bool value)
-{
-       if (json_object_set_new(parent, name, json_boolean(value)))
-               return pr_op_err(
-                   "Cannot convert %s '%u' to json; unknown cause.",
-                   name, value
-               );
-
-       return 0;
-}
-
 int
 json_add_int(json_t *parent, char const *name, int value)
 {
index 5c6dc959968d846998491d4b87958d124a7a8491..33d322926c5c5821a8f9b71001cc592e543ef6a5 100644 (file)
@@ -24,7 +24,6 @@
  * result < 0: Tag was fatally invalid, outbound param reset, logged
  */
 
-int json_get_bool(json_t *, char const *, bool *);
 int json_get_int(json_t *, char const *, int *);
 int json_get_u32(json_t *, char const *, uint32_t *);
 int json_get_ts(json_t *, char const *, time_t *);
@@ -34,7 +33,6 @@ int json_get_object(json_t *, char const *, json_t **);
 
 bool json_valid_members_count(json_t *, size_t);
 
-int json_add_bool(json_t *, char const *, bool);
 int json_add_int(json_t *, char const *, int);
 int json_add_str(json_t *, char const *, char const *);
 int json_add_date(json_t *, char const *, time_t);
index 407c6e9f4becb0fdea4daa516dd6422e6b303b6f..bd4dc248f26d7107de8d7f1cd3258d9c2c62b553 100644 (file)
@@ -73,7 +73,7 @@ struct ad_metadata {
 static const struct ad_metadata CA_ISSUERS = {
        .name = "caIssuers",
        .ia_name = "AIA",
-       .type = UT_RSYNC,
+       .type = UT_AIA,
        .type_str = "rsync",
        .required = true,
 };
@@ -81,7 +81,7 @@ static const struct ad_metadata CA_ISSUERS = {
 static const struct ad_metadata SIGNED_OBJECT = {
        .name = "signedObject",
        .ia_name = "SIA",
-       .type = UT_RSYNC,
+       .type = UT_SO,
        .type_str = "rsync",
        .required = true,
 };
@@ -89,7 +89,7 @@ static const struct ad_metadata SIGNED_OBJECT = {
 static const struct ad_metadata CA_REPOSITORY = {
        .name = "caRepository",
        .ia_name = "SIA",
-       .type = UT_RSYNC,
+       .type = UT_RPP,
        .type_str = "rsync",
        .required = false,
 };
@@ -97,7 +97,7 @@ static const struct ad_metadata CA_REPOSITORY = {
 static const struct ad_metadata RPKI_NOTIFY = {
        .name = "rpkiNotify",
        .ia_name = "SIA",
-       .type = UT_HTTPS,
+       .type = UT_NOTIF,
        .type_str = "HTTPS",
        .required = false,
 };
@@ -105,7 +105,7 @@ static const struct ad_metadata RPKI_NOTIFY = {
 static const struct ad_metadata RPKI_MANIFEST = {
        .name = "rpkiManifest",
        .ia_name = "SIA",
-       .type = UT_RSYNC,
+       .type = UT_MFT,
        .type_str = "rsync",
        .required = true,
 };
@@ -1523,8 +1523,7 @@ uri_create_ad(struct rpki_uri **uri, ACCESS_DESCRIPTION *ad, enum uri_type type,
         * But ask the testers to keep an eye on it anyway.
         */
        return __uri_create(uri,
-           tal_get_file_name(validation_tal(state_retrieve())), type,
-           is_notif, NULL,
+           tal_get_file_name(validation_tal(state_retrieve())), type, NULL,
            ASN1_STRING_get0_data(asn1str), ASN1_STRING_length(asn1str));
 }
 
@@ -1941,7 +1940,8 @@ download_rpp(struct sia_uris *uris)
        }
 
        cache = validation_cache(state_retrieve());
-       error = cache_download_alt(cache, &uris->rpp, true, retrieve_uri, &uri);
+       error = cache_download_alt(cache, &uris->rpp, UT_NOTIF, UT_RPP,
+           retrieve_uri, &uri);
        return error ? NULL : uri;
 }
 
@@ -2034,7 +2034,7 @@ certificate_traverse(struct rpp *rpp_parent, struct rpki_uri *cert_uri)
        cert = NULL; /* Ownership stolen */
 
        error = handle_manifest(sia_uris.mft,
-           (uri_get_type(downloaded) == UT_HTTPS) ? downloaded : NULL,
+           (uri_get_type(downloaded) == UT_NOTIF) ? downloaded : NULL,
            &pp);
        if (error) {
                x509stack_cancel(validation_certstack(state));
index 4ee6c1c1da1bea6508ab354d0440c3afe1850279..f527db86bbb559d7ca9ca43e472b81230f5dabe1 100644 (file)
@@ -323,7 +323,7 @@ fail:
 
 /**
  * Validates the manifest pointed by @uri, returns the RPP described by it in
- * @pp. If @rrdp_workspace is true, use the local RRDP repository.
+ * @pp.
  */
 int
 handle_manifest(struct rpki_uri *uri, struct rpki_uri *notif, struct rpp **pp)
index 14e62c5b5a4447ab2fb693561ffdc08493ed1cea..a9ee59ba228336315426762dd17d84844c780f43 100644 (file)
@@ -77,11 +77,11 @@ add_uri(struct tal *tal, char *uri)
        int error;
 
        if (str_starts_with(uri, "rsync://"))
-               error = uri_create(&new, tal->file_name, UT_RSYNC, false, NULL, uri);
+               error = uri_create(&new, tal->file_name, UT_TA_RSYNC, NULL, uri);
        else if (str_starts_with(uri, "https://"))
-               error = uri_create(&new, tal->file_name, UT_HTTPS, false, NULL, uri);
+               error = uri_create(&new, tal->file_name, UT_TA_HTTP, NULL, uri);
        else
-               return pr_op_err("TAL has non-RSYNC/HTTPS URI: %s", uri);
+               return pr_op_err("TAL has non-rsync/HTTPS URI: %s", uri);
        if (error)
                return error;
 
@@ -303,7 +303,7 @@ do_file_validation(void *arg)
 
        args.db = db_table_create();
        thread->error = cache_download_alt(args.tal.cache, &args.tal.uris,
-           false, __handle_tal_uri, &args);
+           UT_TA_HTTP, UT_TA_RSYNC, __handle_tal_uri, &args);
        if (thread->error) {
                pr_op_err("None of the URIs of the TAL '%s' yielded a successful traversal.",
                    thread->tal_file);
index 4e4255c063b4a739b9e9ee1a25684673eb4b4354..6f60a9edfb9e0c9f98891a4567bd0544b4f3a052 100644 (file)
@@ -422,8 +422,7 @@ parse_file_metadata(xmlTextReaderPtr reader, struct rpki_uri *notif,
                return -EINVAL;
        error = uri_create(&meta->uri,
            tal_get_file_name(validation_tal(state_retrieve())),
-           (notif != NULL) ? UT_CAGED : UT_HTTPS,
-           false, notif, (char const *)uri);
+           (notif != NULL) ? UT_CAGED : UT_TMP, notif, (char const *)uri);
        xmlFree(uri);
        if (error)
                return error;
@@ -780,7 +779,7 @@ handle_snapshot(struct update_notification *notif)
         * Maybe stream it instead.
         * Same for deltas.
         */
-       error = cache_download(validation_cache(state), uri, NULL);
+       error = cache_download(validation_cache(state), uri, 0, NULL);
        if (error)
                goto end;
        error = validate_hash(&notif->snapshot);
@@ -853,7 +852,7 @@ handle_delta(struct update_notification *notif, struct notification_delta *delta
        pr_val_debug("Processing delta '%s'.", uri_val_get_printable(uri));
        fnstack_push_uri(uri);
 
-       error = cache_download(validation_cache(state_retrieve()), uri, NULL);
+       error = cache_download(validation_cache(state_retrieve()), uri, 0, NULL);
        if (error)
                goto end;
        error = parse_delta(notif, delta);
@@ -946,6 +945,7 @@ rrdp_update(struct rpki_uri *uri)
 {
        struct rrdp_session old = { 0 };
        struct update_notification new;
+       time_t ims;
        bool changed;
        int error;
 
@@ -958,7 +958,12 @@ rrdp_update(struct rpki_uri *uri)
        pr_val_debug("Old session/serial: %s/%s", old.session_id,
            old.serial.str);
 
-       error = cache_download(validation_cache(state_retrieve()), uri, &changed);
+       error = file_get_mtim(uri_get_local(uri), &ims);
+       if (error)
+               return error;
+
+       error = cache_download(validation_cache(state_retrieve()), uri,
+           ims, &changed);
        if (error)
                goto end;
        if (!changed) {
index cc7fb74e8a8121d078ec0572582d150358c78e6f..e381bf1823d81315d245b32489840f997cd6088d 100644 (file)
@@ -8,6 +8,7 @@
 #include "state.h"
 #include "str_token.h"
 #include "thread_var.h"
+#include "cache/local_cache.h"
 #include "config/filename_format.h"
 #include "data_structure/path_builder.h"
 
@@ -63,7 +64,6 @@ struct rpki_uri {
        /* "local_len" is never needed right now. */
 
        enum uri_type type;
-       bool is_notif; /* Does it point to an RRDP Notification? */
 
        unsigned int references;
 };
@@ -376,12 +376,25 @@ autocomplete_local(struct rpki_uri *uri, char const *tal,
     struct rpki_uri *notif)
 {
        switch (uri->type) {
-       case UT_RSYNC:
+       case UT_TA_RSYNC:
+       case UT_RPP:
                return map_simple(uri, tal, "rsync://", ENOTRSYNC);
-       case UT_HTTPS:
+
+       case UT_TA_HTTP:
+       case UT_NOTIF:
                return map_simple(uri, tal, "https://", ENOTHTTPS);
+
+       case UT_TMP:
+               return cache_tmpfile(&uri->local);
+
        case UT_CAGED:
                return map_caged(uri, tal, notif);
+
+       case UT_AIA:
+       case UT_SO:
+       case UT_MFT:
+               uri->local = NULL;
+               return 0;
        }
 
        pr_crit("Unknown URI type: %u", uri->type);
@@ -393,7 +406,7 @@ autocomplete_local(struct rpki_uri *uri, char const *tal,
  */
 int
 __uri_create(struct rpki_uri **result, char const *tal, enum uri_type type,
-    bool is_notif, struct rpki_uri *notif, void const *guri, size_t guri_len)
+    struct rpki_uri *notif, void const *guri, size_t guri_len)
 {
        struct rpki_uri *uri;
        int error;
@@ -407,7 +420,6 @@ __uri_create(struct rpki_uri **result, char const *tal, enum uri_type type,
        }
 
        uri->type = type;
-       uri->is_notif = is_notif;
 
        error = autocomplete_local(uri, tal, notif);
        if (error) {
@@ -441,7 +453,7 @@ uri_create_mft(struct rpki_uri **result, char const *tal,
                return error;
        }
 
-       uri->type = (notif == NULL) ? UT_RSYNC : UT_CAGED;
+       uri->type = (notif == NULL) ? UT_RPP : UT_CAGED;
 
        error = autocomplete_local(uri, tal, notif);
        if (error) {
@@ -535,30 +547,12 @@ uri_is_certificate(struct rpki_uri *uri)
        return uri_has_extension(uri, ".cer");
 }
 
-bool
-uri_is_notif(struct rpki_uri *uri)
-{
-       return uri->is_notif;
-}
-
 enum uri_type
 uri_get_type(struct rpki_uri *uri)
 {
        return uri->type;
 }
 
-bool
-uri_is_rsync(struct rpki_uri *uri)
-{
-       return uri->type == UT_RSYNC;
-}
-
-bool
-uri_is_https(struct rpki_uri *uri)
-{
-       return uri->type == UT_HTTPS;
-}
-
 static char const *
 get_filename(char const *file_path)
 {
index 8e7392fbdb810b0de26f01ac8bef3aef2973bd7b..dbfe9c323890ef9873a5779736dec6213434dc8a 100644 (file)
@@ -5,29 +5,30 @@
 #include "data_structure/array_list.h"
 
 enum uri_type {
-       /* rsync URL */
-       UT_RSYNC,
-       /* HTTPS URL */
-       UT_HTTPS,
-       /*
-        * URI (not URL).
-        * In practice it's always rsync, but it doesn't matter.
-        */
-       UT_CAGED,
+       UT_TA_RSYNC, /* TAL's TA URL; downloaded via rsync. */
+       UT_TA_HTTP, /* TAL's TA URL; downloaded via HTTP. */
+       UT_RPP, /* caRepository; downloaded via rsync. */
+       UT_NOTIF, /* rpkiNotify; downloaded via HTTP. */
+       UT_TMP, /* Snapshot or delta; Downloaded via HTTP. */
+       UT_CAGED, /* Endangered species. */
+
+       UT_AIA, /* caIssuers. Not downloaded. */
+       UT_SO, /* signedObject. Not downloaded. */
+       UT_MFT, /* rpkiManifest. Not downloaded. */
 };
 
 struct rpki_uri;
 
 int __uri_create(struct rpki_uri **, char const *, enum uri_type,
-    bool, struct rpki_uri *, void const *, size_t);
+    struct rpki_uri *, void const *, size_t);
 int uri_create_mft(struct rpki_uri **, char const *, struct rpki_uri *,
     struct rpki_uri *, IA5String_t *);
 struct rpki_uri *uri_create_cache(char const *);
 
-#define uri_create(uri, tal, type, is_notif, notif, guri) \
-       __uri_create(uri, tal, type, is_notif, notif, guri, strlen(guri))
+#define uri_create(uri, tal, type, notif, guri) \
+       __uri_create(uri, tal, type, notif, guri, strlen(guri))
 #define uri_create_caged(uri, tal, notif, guri, guri_len) \
-       __uri_create(uri, tal, UT_CAGED, false, notif, guri, guri_len)
+       __uri_create(uri, tal, UT_CAGED, notif, guri, guri_len)
 #define uri_create_cage(uri, tal, notif) \
        uri_create_caged(uri, tal, notif, "", 0)
 
@@ -45,11 +46,8 @@ size_t uri_get_global_len(struct rpki_uri *);
 bool uri_equals(struct rpki_uri *, struct rpki_uri *);
 bool uri_has_extension(struct rpki_uri *, char const *);
 bool uri_is_certificate(struct rpki_uri *);
-bool uri_is_notif(struct rpki_uri *);
 
 enum uri_type uri_get_type(struct rpki_uri *);
-bool uri_is_rsync(struct rpki_uri *);
-bool uri_is_https(struct rpki_uri *);
 
 char const *uri_val_get_printable(struct rpki_uri *);
 char const *uri_op_get_printable(struct rpki_uri *);
index 3cd53ae71ab1e6f4ecc764558f701a42c7d0471b..054c3f6754960cd83606602a937770935833a2cf 100644 (file)
@@ -57,6 +57,15 @@ file_rm_rf(char const *file)
        return ENOENT;
 }
 
+int
+file_rm_f(char const *file)
+{
+       file_rm_rf(file);
+       return 0;
+}
+
+MOCK_ABORT_INT(file_get_mtim, char const *file, time_t *ims)
+
 static int
 pretend_download(struct rpki_uri *uri)
 {
@@ -82,7 +91,7 @@ rsync_download(struct rpki_uri *uri)
 }
 
 int
-http_download(struct rpki_uri *uri, bool *changed)
+http_download(struct rpki_uri *uri, curl_off_t ims, bool *changed)
 {
        int error;
        https_counter++;
@@ -115,17 +124,17 @@ run_cache_download(char const *url, int expected_error,
        enum uri_type type;
 
        if (str_starts_with(url, "https://"))
-               type = UT_HTTPS;
+               type = UT_TA_HTTP;
        else if (str_starts_with(url, "rsync://"))
-               type = UT_RSYNC;
+               type = UT_RPP;
        else
                ck_abort_msg("Bad protocol: %s", url);
 
        rsync_counter = 0;
        https_counter = 0;
 
-       ck_assert_int_eq(0, uri_create(&uri, TAL_FILE, type, false, NULL, url));
-       ck_assert_int_eq(expected_error, cache_download(cache, uri, NULL));
+       ck_assert_int_eq(0, uri_create(&uri, TAL_FILE, type, NULL, url));
+       ck_assert_int_eq(expected_error, cache_download(cache, uri, 0, NULL));
        ck_assert_uint_eq(rsync_calls, rsync_counter);
        ck_assert_uint_eq(https_calls, https_counter);
 
@@ -140,15 +149,14 @@ node(char const *url, time_t attempt, int err, bool succeeded, time_t success,
        struct cache_node *result;
 
        if (str_starts_with(url, "https://"))
-               type = UT_HTTPS;
+               type = is_notif ? UT_NOTIF : UT_TA_HTTP;
        else if (str_starts_with(url, "rsync://"))
-               type = UT_RSYNC;
+               type = UT_RPP;
        else
                ck_abort_msg("Bad protocol: %s", url);
 
        result = pzalloc(sizeof(struct cache_node));
-       ck_assert_int_eq(0, uri_create(&result->url, TAL_FILE, type, is_notif,
-           NULL, url));
+       ck_assert_int_eq(0, uri_create(&result->url, TAL_FILE, type, NULL, url));
        result->attempt.ts = attempt;
        result->attempt.result = err;
        result->success.happened = succeeded;
@@ -735,11 +743,11 @@ START_TEST(test_tal_json)
        json_decref(json);
 
        ck_assert_str_eq(
-           "[{\"url\":\"rsync://a.b.c/d\",\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":0,\"success-timestamp\":\"1970-01-01T00:00:00Z\"},"
-           "{\"url\":\"rsync://a.b.c/e\",\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":1},"
-           "{\"url\":\"rsync://x.y.z/e\",\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":0,\"success-timestamp\":\"1970-01-01T00:00:00Z\"},"
-           "{\"url\":\"https://a/b\",\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":1,\"success-timestamp\":\"1970-01-01T00:00:00Z\"},"
-           "{\"url\":\"https://a/c\",\"is-rrdp-notification\":true,\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":0,\"success-timestamp\":\"1970-01-01T00:00:00Z\"}]",
+           "[{\"type\":\"RPP\",\"url\":\"rsync://a.b.c/d\",\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":0,\"success-timestamp\":\"1970-01-01T00:00:00Z\"},"
+           "{\"type\":\"RPP\",\"url\":\"rsync://a.b.c/e\",\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":1},"
+           "{\"type\":\"RPP\",\"url\":\"rsync://x.y.z/e\",\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":0,\"success-timestamp\":\"1970-01-01T00:00:00Z\"},"
+           "{\"type\":\"TA (HTTP)\",\"url\":\"https://a/b\",\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":1,\"success-timestamp\":\"1970-01-01T00:00:00Z\"},"
+           "{\"type\":\"RRDP Notification\",\"url\":\"https://a/c\",\"attempt-timestamp\":\"1970-01-01T00:00:00Z\",\"attempt-result\":0,\"success-timestamp\":\"1970-01-01T00:00:00Z\"}]",
            str);
        free(str);
 
@@ -773,13 +781,12 @@ prepare_uri_list(struct uri_list *uris, ...)
        va_start(args, uris);
        while ((str = va_arg(args, char const *)) != NULL) {
                if (str_starts_with(str, "https://"))
-                       type = UT_HTTPS;
+                       type = UT_TA_HTTP;
                else if (str_starts_with(str, "rsync://"))
-                       type = UT_RSYNC;
+                       type = UT_RPP;
                else
                        ck_abort_msg("Bad protocol: %s", str);
-               ck_assert_int_eq(0, uri_create(&uri, TAL_FILE, type, false,
-                   NULL, str));
+               ck_assert_int_eq(0, uri_create(&uri, TAL_FILE, type, NULL, str));
                uris_add(uris, uri);
        }
        va_end(args);
@@ -795,7 +802,7 @@ START_TEST(test_recover)
 
        /* Query on empty database */
        PREPARE_URI_LIST(&uris, "rsync://a.b.c/d", "https://a.b.c/d");
-       ck_assert_ptr_eq(NULL, cache_recover(cache, &uris, false));
+       ck_assert_ptr_eq(NULL, cache_recover(cache, &uris));
        uris_cleanup(&uris);
 
        /* Only first URI is cached */
@@ -803,7 +810,7 @@ START_TEST(test_recover)
        run_cache_download("rsync://a/b/c", 0, 1, 0);
 
        PREPARE_URI_LIST(&uris, "rsync://a/b/c", "https://d/e", "https://f");
-       ck_assert_ptr_eq(uris.array[0], cache_recover(cache, &uris, false));
+       ck_assert_ptr_eq(uris.array[0], cache_recover(cache, &uris));
        uris_cleanup(&uris);
 
        /* Only second URI is cached */
@@ -811,7 +818,7 @@ START_TEST(test_recover)
        run_cache_download("https://d/e", 0, 0, 1);
 
        PREPARE_URI_LIST(&uris, "rsync://a/b/c", "https://d/e", "https://f");
-       ck_assert_ptr_eq(uris.array[1], cache_recover(cache, &uris, false));
+       ck_assert_ptr_eq(uris.array[1], cache_recover(cache, &uris));
        uris_cleanup(&uris);
 
        /* Only third URI is cached */
@@ -819,7 +826,7 @@ START_TEST(test_recover)
        run_cache_download("https://f", 0, 0, 1);
 
        PREPARE_URI_LIST(&uris, "rsync://a/b/c", "https://d/e", "https://f");
-       ck_assert_ptr_eq(uris.array[2], cache_recover(cache, &uris, false));
+       ck_assert_ptr_eq(uris.array[2], cache_recover(cache, &uris));
        uris_cleanup(&uris);
 
        /* None was cached */
@@ -827,7 +834,7 @@ START_TEST(test_recover)
        run_cache_download("rsync://d/e", 0, 1, 0);
 
        PREPARE_URI_LIST(&uris, "rsync://a/b/c", "https://d/e", "https://f");
-       ck_assert_ptr_eq(NULL, cache_recover(cache, &uris, false));
+       ck_assert_ptr_eq(NULL, cache_recover(cache, &uris));
        uris_cleanup(&uris);
 
        /*
@@ -854,21 +861,21 @@ START_TEST(test_recover)
 
        /* Multiple successful caches: Prioritize the most recent one */
        PREPARE_URI_LIST(&uris, "rsync://a/1", "rsync://a/3", "rsync://a/5");
-       ck_assert_ptr_eq(uris.array[2], cache_recover(cache, &uris, false));
+       ck_assert_ptr_eq(uris.array[2], cache_recover(cache, &uris));
        uris_cleanup(&uris);
 
        PREPARE_URI_LIST(&uris, "rsync://a/5", "rsync://a/1", "rsync://a/3");
-       ck_assert_ptr_eq(uris.array[0], cache_recover(cache, &uris, false));
+       ck_assert_ptr_eq(uris.array[0], cache_recover(cache, &uris));
        uris_cleanup(&uris);
 
        /* No successful caches: No viable candidates */
        PREPARE_URI_LIST(&uris, "rsync://b/2", "rsync://b/4", "rsync://b/6");
-       ck_assert_ptr_eq(NULL, cache_recover(cache, &uris, false));
+       ck_assert_ptr_eq(NULL, cache_recover(cache, &uris));
        uris_cleanup(&uris);
 
        /* Status: CNF_SUCCESS is better than 0. */
        PREPARE_URI_LIST(&uris, "rsync://b/1", "rsync://a/1");
-       ck_assert_ptr_eq(uris.array[1], cache_recover(cache, &uris, false));
+       ck_assert_ptr_eq(uris.array[1], cache_recover(cache, &uris));
        uris_cleanup(&uris);
 
        /*
@@ -879,12 +886,12 @@ START_TEST(test_recover)
         * outdatedness is not that severe.
         */
        PREPARE_URI_LIST(&uris, "rsync://a/2", "rsync://b/2");
-       ck_assert_ptr_eq(uris.array[0], cache_recover(cache, &uris, false));
+       ck_assert_ptr_eq(uris.array[0], cache_recover(cache, &uris));
        uris_cleanup(&uris);
 
        /* Parents of downloaded nodes */
        PREPARE_URI_LIST(&uris, "rsync://a", "rsync://b");
-       ck_assert_ptr_eq(NULL, cache_recover(cache, &uris, false));
+       ck_assert_ptr_eq(NULL, cache_recover(cache, &uris));
        uris_cleanup(&uris);
 
        /* Try them all at the same time */
@@ -894,7 +901,7 @@ START_TEST(test_recover)
            "rsync://b", "rsync://b/1", "rsync://b/2", "rsync://b/3",
            "rsync://b/4", "rsync://b/5", "rsync://b/6",
            "rsync://e/1");
-       ck_assert_ptr_eq(uris.array[5], cache_recover(cache, &uris, false));
+       ck_assert_ptr_eq(uris.array[5], cache_recover(cache, &uris));
        uris_cleanup(&uris);
 
        cleanup_test();
index cbd4a86c7bc15e85bdb706bf79051c2af24ef381..5673aa5891cedf85197d2eaf7dca823bba2ba11e 100644 (file)
@@ -9,6 +9,8 @@
 #include "types/uri.c"
 #include "crypto/hash.c"
 
+MOCK_ABORT_INT(cache_tmpfile, char **filename)
+
 /* Actually mostly tests libcrypto's sanity, not Fort's. */
 START_TEST(test_hash)
 {
@@ -45,8 +47,7 @@ START_TEST(test_hash)
        uri.global = "https://example.com/resources/lorem-ipsum.txt";
        uri.global_len = strlen(uri.global);
        uri.local = "resources/lorem-ipsum.txt";
-       uri.type = UT_HTTPS;
-       uri.is_notif = false;
+       uri.type = UT_TA_HTTP;
        uri.references = 1;
 
        ha = hash_get_sha1();
index 60595ef45c9c13313a7731fbe65682a793c952e4..e5ac7acbea01ad8379218e1bd953ce299468e205 100644 (file)
 
 /* Mocks */
 
+int
+cache_tmpfile(char **filename)
+{
+       static unsigned int file_counter = 0;
+       char *result;
+       int written;
+
+       result = pmalloc(10);
+       written = snprintf(result, 10, "tmp/%u", file_counter);
+       ck_assert(4 < written && written < 10);
+
+       *filename = result;
+       return 0;
+}
+
 MOCK_ABORT_INT(cache_download, struct rpki_cache *cache, struct rpki_uri *uri,
-    bool *changed)
+    curl_off_t ims, bool *changed)
 MOCK_ABORT_VOID(fnstack_pop, void)
 MOCK_ABORT_VOID(fnstack_push_uri, struct rpki_uri *uri)
 MOCK_ABORT_PTR(validation_cache, rpki_cache, struct validation *state)
@@ -242,6 +257,7 @@ START_TEST(test_parse_notification_ok)
 
        ck_assert_int_eq(0, relax_ng_init());
        uri.local = "resources/rrdp/notif-ok.xml";
+       uri.type = UT_NOTIF;
        uri.references = 1;
        ck_assert_int_eq(0, parse_notification(&uri, &notif));
 
@@ -276,6 +292,7 @@ START_TEST(test_parse_notification_0deltas)
 
        ck_assert_int_eq(0, relax_ng_init());
        uri.local = "resources/rrdp/notif-0deltas.xml";
+       uri.type = UT_NOTIF;
        uri.references = 1;
        ck_assert_int_eq(0, parse_notification(&uri, &notif));
 
@@ -300,6 +317,7 @@ START_TEST(test_parse_notification_large_serial)
 
        ck_assert_int_eq(0, relax_ng_init());
        uri.local = "resources/rrdp/notif-large-serial.xml";
+       uri.type = UT_NOTIF;
        uri.references = 1;
        ck_assert_int_eq(0, parse_notification(&uri, &notif));
 
@@ -331,6 +349,7 @@ test_parse_notification_error(char *file)
 
        ck_assert_int_eq(0, relax_ng_init());
        uri.local = file;
+       uri.type = UT_NOTIF;
        uri.references = 1;
        ck_assert_int_eq(-EINVAL, parse_notification(&uri, &notif));
 
@@ -396,8 +415,7 @@ START_TEST(test_parse_snapshot_bad_publish)
        notif_uri.global = "https://example.com/notification.xml";
        notif_uri.global_len = strlen(notif_uri.global);
        notif_uri.local = "cache/example.com/notification.xml";
-       notif_uri.type = UT_HTTPS;
-       notif_uri.is_notif = true;
+       notif_uri.type = UT_NOTIF;
        notif_uri.references = 1;
 
        snapshot_uri.local = "resources/rrdp/snapshot-bad-publish.xml";
index 5001f8febabdf360e903d29ef8d38bed0af4bc33..8adf18f0ad6fdf31d091e792d9040513ef1131ed 100644 (file)
@@ -16,11 +16,13 @@ MOCK_ABORT_VOID(cache_setup, void)
 MOCK(cache_create, struct rpki_cache *, NULL, char const *tal)
 MOCK_VOID(cache_destroy, struct rpki_cache *cache)
 MOCK_ABORT_INT(cache_download, struct rpki_cache *cache, struct rpki_uri *uri,
-    bool *changed)
+    curl_off_t ims, bool *changed)
 MOCK_ABORT_INT(cache_download_alt, struct rpki_cache *cache,
-    struct uri_list *uris, bool use_rrdp, uris_dl_cb cb, void *arg)
+    struct uri_list *uris, enum uri_type http_type, enum uri_type rsync_type,
+    uris_dl_cb cb, void *arg)
 MOCK_ABORT_PTR(cache_recover, rpki_uri, struct rpki_cache *cache,
-    struct uri_list *uris, bool use_rrdp)
+    struct uri_list *uris)
+MOCK_ABORT_INT(cache_tmpfile, char **filename)
 MOCK_ABORT_VOID(cache_teardown, void)
 MOCK_ABORT_INT(certificate_traverse, struct rpp *rpp_parent,
     struct rpki_uri *cert_uri)
index d81960936f44015f65901b8a16a46a9a5f037f55..8b611e8dfdcbe497226cf81888a15cd99dbe4610 100644 (file)
@@ -18,10 +18,25 @@ MOCK(tal_get_file_name, char const *, "test.tal", struct tal *tal)
 
 MOCK_ABORT_INT(rrdp_update, struct rpki_uri *uri)
 
+int
+cache_tmpfile(char **filename)
+{
+       static bool used = false;
+
+       if (used) {
+               ck_abort_msg("cache_tmpfile() called a second time!");
+               return -EINVAL;
+       }
+
+       *filename = pstrdup("tmp/tmp/0");
+       used = true;
+       return 0;
+}
+
 /* Tests */
 
-#define URI_CREATE_HTTP(uri, str) uri_create(&uri, "test.tal", UT_HTTPS, false, NULL, str)
-#define URI_CREATE_RSYNC(uri, str) uri_create(&uri, "test.tal", UT_RSYNC, false, NULL, str)
+#define URI_CREATE_HTTP(uri, str) uri_create(&uri, "test.tal", UT_TA_HTTP, NULL, str)
+#define URI_CREATE(uri, type, str) uri_create(&uri, "test.tal", type, NULL, str)
 
 START_TEST(test_constructor)
 {
@@ -87,7 +102,27 @@ START_TEST(test_constructor)
 
        ck_assert_int_eq(ENOTHTTPS, URI_CREATE_HTTP(uri, "rsync://a.b.c/d"));
        ck_assert_int_eq(ENOTHTTPS, URI_CREATE_HTTP(uri, "http://a.b.c/d"));
-       ck_assert_int_eq(ENOTRSYNC, URI_CREATE_RSYNC(uri, "https://a.b.c/d"));
+       ck_assert_int_eq(ENOTRSYNC, URI_CREATE(uri, UT_RPP, "https://a.b.c/d"));
+
+       ck_assert_int_eq(0, URI_CREATE(uri, UT_RPP, "rsync://a.b.c/d"));
+       ck_assert_str_eq("rsync://a.b.c/d", uri_get_global(uri));
+       ck_assert_str_eq("tmp/test.tal/rsync/a.b.c/d", uri_get_local(uri));
+       uri_refput(uri);
+
+       ck_assert_int_eq(0, URI_CREATE(uri, UT_TA_RSYNC, "rsync://a.b.c/d.cer"));
+       ck_assert_str_eq("rsync://a.b.c/d.cer", uri_get_global(uri));
+       ck_assert_str_eq("tmp/test.tal/rsync/a.b.c/d.cer", uri_get_local(uri));
+       uri_refput(uri);
+
+       ck_assert_int_eq(0, URI_CREATE(uri, UT_NOTIF, "https://a.b.c/notification.xml"));
+       ck_assert_str_eq("https://a.b.c/notification.xml", uri_get_global(uri));
+       ck_assert_str_eq("tmp/test.tal/https/a.b.c/notification.xml", uri_get_local(uri));
+       uri_refput(uri);
+
+       ck_assert_int_eq(0, URI_CREATE(uri, UT_TMP, "https://a.b.c/snapshot.xml"));
+       ck_assert_str_eq("https://a.b.c/snapshot.xml", uri_get_global(uri));
+       ck_assert_str_eq("tmp/tmp/0", uri_get_local(uri));
+       uri_refput(uri);
 }
 END_TEST
 
@@ -147,14 +182,14 @@ START_TEST(check_caged)
 {
        struct rpki_uri *uri;
 
-       ck_assert_int_eq(0, uri_create(&notif, "test.tal", UT_HTTPS, true, NULL, "https://a.b.c/d/e.xml"));
-       ck_assert_int_eq(0, uri_create(&uri, "test.tal", UT_CAGED, false, notif, "rsync://x.y.z/v/w.cer"));
+       ck_assert_int_eq(0, uri_create(&notif, "test.tal", UT_NOTIF, NULL, "https://a.b.c/d/e.xml"));
+       ck_assert_int_eq(0, uri_create(&uri, "test.tal", UT_CAGED, notif, "rsync://x.y.z/v/w.cer"));
        ck_assert_str_eq("tmp/test.tal/rrdp/a.b.c/d/e.xml/x.y.z/v/w.cer", uri_get_local(uri));
        uri_refput(uri);
        uri_refput(notif);
 
-       ck_assert_int_eq(0, uri_create(&notif, "test.tal", UT_HTTPS, true, NULL, "https://a.b.c"));
-       ck_assert_int_eq(0, uri_create(&uri, "test.tal", UT_CAGED, false, notif, "rsync://w"));
+       ck_assert_int_eq(0, uri_create(&notif, "test.tal", UT_NOTIF, NULL, "https://a.b.c"));
+       ck_assert_int_eq(0, uri_create(&uri, "test.tal", UT_CAGED, notif, "rsync://w"));
        ck_assert_str_eq("tmp/test.tal/rrdp/a.b.c/w", uri_get_local(uri));
        uri_refput(uri);
        uri_refput(notif);