diff options
author | Vivien Kraus <vivien@planete-kraus.eu> | 2023-03-21 20:51:00 +0100 |
---|---|---|
committer | Vivien Kraus <vivien@planete-kraus.eu> | 2023-03-25 13:24:39 +0100 |
commit | 2c04502589876dc4c19bdbff4426757571ac76b0 (patch) | |
tree | 302bbb198829c00b51a64898cb6510c3da43d955 /src | |
parent | b7a76711ed9898dca90b91f87c5dcbd49be9553e (diff) |
Optionally store a key, response header and body in a cache entry
Diffstat (limited to 'src')
-rw-r--r-- | src/libdisfluid/disfluid-cache-entry.h | 527 | ||||
-rw-r--r-- | src/libdisfluid/disfluid-tests.h | 129 | ||||
-rw-r--r-- | src/libdisfluid/main.c | 46 |
3 files changed, 608 insertions, 94 deletions
diff --git a/src/libdisfluid/disfluid-cache-entry.h b/src/libdisfluid/disfluid-cache-entry.h index eb09cdf..ea76217 100644 --- a/src/libdisfluid/disfluid-cache-entry.h +++ b/src/libdisfluid/disfluid-cache-entry.h @@ -4,8 +4,7 @@ MAYBE_UNUSED static size_t cache_entry_size (size_t max_key, size_t max_header, size_t max_body); -MAYBE_UNUSED static size_t -cache_entry_alignment (size_t max_key, size_t max_header, size_t max_body); +MAYBE_UNUSED static size_t cache_entry_alignment (void); MAYBE_UNUSED static void cache_entry_init (struct disfluid_cache_entry *entry, size_t max_key, @@ -16,6 +15,10 @@ cache_entry_minimum_size (const struct disfluid_cache_entry *entry, size_t *used_key, size_t *used_header, size_t *used_body); +MAYBE_UNUSED static int +cache_entry_copy (struct disfluid_cache_entry *restrict dest, + const struct disfluid_cache_entry *restrict src); + MAYBE_UNUSED static struct disfluid_cache_entry *cache_entry_alloc (size_t max_key, size_t max_header, size_t max_body); @@ -40,18 +43,36 @@ MAYBE_UNUSED static void cache_entry_set_invalidated (struct disfluid_cache_entry *entry, bool invalidated); +MAYBE_UNUSED static int +cache_entry_set_key (struct disfluid_cache_entry *entry, const char *key); + +MAYBE_UNUSED static int +cache_entry_set_response_header (struct disfluid_cache_entry *entry, + const char *header); + +MAYBE_UNUSED static int +cache_entry_set_response_body (struct disfluid_cache_entry *entry, + size_t length, const char *body); + /* Return value: 0 -> OK, -1 -> read_impl error, -2 -> invalid file, - -3 -> incomplete file. */ + -3 -> incomplete file, -4 -> key too large, -5 -> header too large, + -6 -> body too large. */ MAYBE_UNUSED static int cache_entry_load (struct disfluid_cache_entry *entry, + int load_key, + int load_header, + int load_body, ssize_t (*read_impl) (void *context, void *buffer, - size_t max_size), void *context); + size_t max_size), + int (*skip) (void *context, size_t size), void *context); MAYBE_UNUSED static int -cache_entry_read (struct disfluid_cache_entry *entry, int fd); +cache_entry_read (struct disfluid_cache_entry *entry, int load_key, + int load_header, int load_body, int fd); MAYBE_UNUSED static int -cache_entry_fread (struct disfluid_cache_entry *entry, FILE * f); +cache_entry_fread (struct disfluid_cache_entry *entry, int load_key, + int load_header, int load_body, FILE * f); MAYBE_UNUSED static void cache_entry_get_request_date (const struct disfluid_cache_entry *entry, @@ -64,7 +85,25 @@ cache_entry_get_response_date (const struct disfluid_cache_entry *entry, MAYBE_UNUSED static bool cache_entry_is_invalidated (const struct disfluid_cache_entry *entry); -/* -1: write_impl failed. 0: OK. */ +MAYBE_UNUSED static void +cache_entry_is_loaded (const struct disfluid_cache_entry *entry, + bool *key_loaded, bool *header_loaded, + bool *body_loaded); + +/* If max is too large, key will be NUL-terminated. */ +MAYBE_UNUSED static size_t +cache_entry_get_key (const struct disfluid_cache_entry *entry, size_t start, + size_t max, char *key); + +MAYBE_UNUSED static size_t +cache_entry_get_header (const struct disfluid_cache_entry *entry, + size_t start, size_t max, char *header); + +MAYBE_UNUSED static size_t +cache_entry_get_body (const struct disfluid_cache_entry *entry, size_t start, + size_t max, char *body); + +/* -1: write_impl failed. 0: OK. -2: the entry is not fully loaded. */ MAYBE_UNUSED static int cache_entry_save (const struct disfluid_cache_entry *entry, ssize_t (*write_impl) (void *context, const void *buffer, @@ -77,69 +116,69 @@ MAYBE_UNUSED static int cache_entry_fwrite (const struct disfluid_cache_entry *entry, FILE * f); # include <assert.h> +# include <flexmember.h> # include "disfluid-init.h" +# define INVALIDATED 0b1000 +# define KEY_NOT_LOADED 0b0001 +# define HEADER_NOT_LOADED 0b0010 +# define BODY_NOT_LOADED 0b0100 + struct disfluid_cache_entry { struct timespec request_date; struct timespec response_date; - bool invalidated; + int flags; size_t max_key; size_t max_header; size_t max_body; + size_t key_length; + size_t header_length; + size_t body_length; + char data[FLEXIBLE_ARRAY_MEMBER]; /* Contains max_key + 1 + + max_header + 1 + max_body + elements */ + /* The key and header are NUL-terminated in memory. */ }; -static void * +static char * +cache_entry_internal_data (struct disfluid_cache_entry *entry) +{ + return &(entry->data[0]); +} + +static char * cache_entry_key (struct disfluid_cache_entry *entry) { - size_t entry_offset; - memcpy (&entry_offset, &entry, sizeof (entry)); - size_t key_offset = entry_offset + sizeof (struct disfluid_cache_entry); - void *ret; - memcpy (&ret, &key_offset, sizeof (size_t)); - return ret; + return cache_entry_internal_data (entry); } -static void * +static char * cache_entry_header (struct disfluid_cache_entry *entry) { - size_t entry_offset; - memcpy (&entry_offset, &entry, sizeof (entry)); - size_t header_offset = - entry_offset + sizeof (struct disfluid_cache_entry) + entry->max_key; - void *ret; - memcpy (&ret, &header_offset, sizeof (size_t)); - return ret; + char *key = cache_entry_key (entry); + return &(key[entry->max_key + 1]); } -static void * +static char * cache_entry_body (struct disfluid_cache_entry *entry) { - size_t entry_offset; - memcpy (&entry_offset, &entry, sizeof (entry)); - size_t body_offset = - entry_offset + sizeof (struct disfluid_cache_entry) - + entry->max_key + entry->max_header; - void *ret; - memcpy (&ret, &body_offset, sizeof (size_t)); - return ret; + char *key = cache_entry_header (entry); + return &(key[entry->max_header + 1]); } static size_t cache_entry_size (size_t max_key, size_t max_header, size_t max_body) { - return sizeof (struct disfluid_cache_entry) - + max_key + max_header + max_body; + return FLEXSIZEOF (struct disfluid_cache_entry, data, + max_key + 1 + max_header + 1 + max_body); } static size_t -cache_entry_alignment (size_t max_key, size_t max_header, size_t max_body) +cache_entry_alignment (void) { - (void) max_key; - (void) max_header; - (void) max_body; - return alignof (struct disfluid_cache_entry); + return FLEXALIGNOF (struct disfluid_cache_entry); } static void @@ -151,10 +190,17 @@ cache_entry_init (struct disfluid_cache_entry *entry, size_t max_key, entry->request_date.tv_nsec = 0; entry->response_date.tv_sec = 0; entry->response_date.tv_nsec = 0; - entry->invalidated = false; + entry->flags = KEY_NOT_LOADED | HEADER_NOT_LOADED | BODY_NOT_LOADED; entry->max_key = max_key; entry->max_header = max_header; entry->max_body = max_body; + entry->key_length = 0; + entry->header_length = 0; + entry->body_length = 0; + char *key = cache_entry_key (entry); + char *header = cache_entry_key (entry); + *key = '\0'; + *header = '\0'; } static void @@ -163,9 +209,16 @@ cache_entry_minimum_size (const struct disfluid_cache_entry *entry, size_t *min_body) { (void) entry; - *min_key = 0; - *min_header = 0; - *min_body = 0; + *min_key = entry->key_length; + *min_header = entry->header_length; + *min_body = entry->body_length; + assert (entry->flags & KEY_NOT_LOADED + || (strlen (cache_entry_key ((struct disfluid_cache_entry *) entry)) + == entry->key_length)); + assert (entry->flags & HEADER_NOT_LOADED + || + (strlen (cache_entry_header ((struct disfluid_cache_entry *) entry)) + == entry->header_length)); } static int @@ -176,17 +229,17 @@ cache_entry_copy (struct disfluid_cache_entry *restrict dest, dest->request_date.tv_nsec = src->request_date.tv_nsec; dest->response_date.tv_sec = src->response_date.tv_sec; dest->response_date.tv_nsec = src->response_date.tv_nsec; - dest->invalidated = src->invalidated; + dest->flags = src->flags; size_t src_key_size, src_header_size, src_body_size; cache_entry_minimum_size (src, &src_key_size, &src_header_size, &src_body_size); - void *dest_key = cache_entry_key (dest); - void *dest_header = cache_entry_header (dest); - void *dest_body = cache_entry_body (dest); - const void *src_key = cache_entry_key ((struct disfluid_cache_entry *) src); - const void *src_header = + char *dest_key = cache_entry_key (dest); + char *dest_header = cache_entry_header (dest); + char *dest_body = cache_entry_body (dest); + const char *src_key = cache_entry_key ((struct disfluid_cache_entry *) src); + const char *src_header = cache_entry_header ((struct disfluid_cache_entry *) src); - const void *src_body = + const char *src_body = cache_entry_body ((struct disfluid_cache_entry *) src); int flags = 0; if (src_key_size > dest->max_key) @@ -203,9 +256,18 @@ cache_entry_copy (struct disfluid_cache_entry *restrict dest, } if (flags == 0) { - memcpy (dest_key, src_key, src_key_size); - memcpy (dest_header, src_header, src_header_size); - memcpy (dest_body, src_body, src_body_size); + if (!(src->flags & KEY_NOT_LOADED)) + { + strcpy (dest_key, src_key); + } + if (!(src->flags & HEADER_NOT_LOADED)) + { + strcpy (dest_header, src_header); + } + if (!(src->flags & BODY_NOT_LOADED)) + { + memcpy (dest_body, src_body, src_body_size); + } } return -flags; } @@ -214,8 +276,7 @@ static struct disfluid_cache_entry * cache_entry_alloc (size_t max_key, size_t max_header, size_t max_body) { const size_t size = cache_entry_size (max_key, max_header, max_body); - const size_t alignment = - cache_entry_alignment (max_key, max_header, max_body); + const size_t alignment = cache_entry_alignment (); struct disfluid_cache_entry *ret = calloc (1, size); if (ret != NULL) { @@ -287,14 +348,62 @@ cache_entry_set_response_date (struct disfluid_cache_entry *entry, static void cache_entry_invalidate (struct disfluid_cache_entry *entry) { - entry->invalidated = true; + cache_entry_set_invalidated (entry, true); } static void cache_entry_set_invalidated (struct disfluid_cache_entry *entry, bool invalidated) { - entry->invalidated = invalidated; + if (invalidated) + { + entry->flags = entry->flags | INVALIDATED; + } + else + { + entry->flags = entry->flags & ~INVALIDATED; + } +} + +static int +cache_entry_set_key (struct disfluid_cache_entry *entry, const char *key) +{ + if (strlen (key) < entry->max_key) + { + strcpy (cache_entry_key (entry), key); + entry->key_length = strlen (key); + entry->flags = entry->flags & ~KEY_NOT_LOADED; + return 0; + } + return -1; +} + +static int +cache_entry_set_response_header (struct disfluid_cache_entry *entry, + const char *header) +{ + if (strlen (header) < entry->max_header) + { + strcpy (cache_entry_header (entry), header); + entry->header_length = strlen (header); + entry->flags = entry->flags & ~HEADER_NOT_LOADED; + return 0; + } + return -1; +} + +static int +cache_entry_set_response_body (struct disfluid_cache_entry *entry, + size_t length, const char *body) +{ + if (length <= entry->max_body) + { + memcpy (cache_entry_body (entry), body, length); + entry->body_length = length; + entry->flags = entry->flags & ~BODY_NOT_LOADED; + return 0; + } + return -1; } /* The cache entry file is composed as: */ @@ -305,10 +414,17 @@ cache_entry_set_invalidated (struct disfluid_cache_entry *entry, tv_nsec field (must be < 1e9). */ /* The response date on 12 bytes. */ /* On 1 byte: a value >= 128 if invalidated, < 128 if still valid. */ +/* On 8 bytes: the key length. */ +/* The key. */ +/* On 8 bytes: the header length. */ +/* The header. */ +/* On 8 bytes: the body length. */ +/* The body. */ struct disfluid_cache_entry_loader { ssize_t (*read_impl) (void *, void *, size_t); + int (*skip) (void *, size_t); void *context; }; @@ -338,6 +454,12 @@ cache_entry_really_load_n (struct disfluid_cache_entry_loader *loader, } static int +cache_entry_skip_n (struct disfluid_cache_entry_loader *loader, size_t n) +{ + return loader->skip (loader->context, n); +} + +static int cache_entry_load_magic (struct disfluid_cache_entry_loader *loader) { uint8_t magic[16]; @@ -393,12 +515,118 @@ cache_entry_load_flags (struct disfluid_cache_entry_loader *loader, } static int +cache_entry_skip_or_load_section (struct disfluid_cache_entry_loader *loader, + int mode, + int flag_bit, + int *restrict flags_value, + size_t *restrict length, + bool nul_terminate, + size_t max_data, char *restrict data) +{ + uint8_t size[sizeof (*length)] = { 0 }; + int error = cache_entry_really_load_n (loader, sizeof (size), size); + if (error) + { + return error; + } + *length = 0; + for (size_t i = 0; i < sizeof (size); i++) + { + *length *= 256; + *length += size[i]; + } + if (*length > max_data) + { + return -4; + } + if (mode <= 0) + { + if (mode < 0) + { + *flags_value = *flags_value | flag_bit; + if (max_data != 0) + { + *data = '\0'; + } + } + error = cache_entry_skip_n (loader, *length); + } + else + { + error = cache_entry_really_load_n (loader, *length, (uint8_t *) data); + } + if (error == 0 && nul_terminate) + { + /* We are allowed to access data[max_data]. */ + data[*length] = '\0'; + } + return error; +} + +static int +cache_entry_skip_or_load_key (struct disfluid_cache_entry_loader *loader, + int mode, + int *restrict flags, + size_t *restrict length, + size_t max_data, char *restrict data) +{ + int error = cache_entry_skip_or_load_section (loader, mode, KEY_NOT_LOADED, + flags, length, true, max_data, + data); + if (error == -4) + { + /* -4 means the recipient is too small. Coincidentally, it is + also the correct return value for cache_entry_load. */ + return -4; + } + return error; +} + +static int +cache_entry_skip_or_load_header (struct disfluid_cache_entry_loader *loader, + int mode, + int *restrict flags, + size_t *restrict length, + size_t max_data, char *restrict data) +{ + int error = + cache_entry_skip_or_load_section (loader, mode, HEADER_NOT_LOADED, + flags, length, true, max_data, data); + if (error == -4) + { + return -5; + } + return error; +} + +static int +cache_entry_skip_or_load_body (struct disfluid_cache_entry_loader *loader, + int mode, + int *restrict flags, + size_t *restrict length, + size_t max_data, char *restrict data) +{ + int error = cache_entry_skip_or_load_section (loader, mode, BODY_NOT_LOADED, + flags, length, true, max_data, + data); + if (error == -4) + { + return -6; + } + return error; +} + +static int cache_entry_load (struct disfluid_cache_entry *entry, + int load_key, + int load_header, + int load_body, ssize_t (*read_impl) (void *, void *, size_t), - void *context) + int (*skip) (void *, size_t), void *context) { struct disfluid_cache_entry_loader loader = { .read_impl = read_impl, + .skip = skip, .context = context }; int error = 0; @@ -422,6 +650,29 @@ cache_entry_load (struct disfluid_cache_entry *entry, } if (error == 0) { + error = + cache_entry_skip_or_load_key (&loader, load_key, &(entry->flags), + &(entry->key_length), entry->max_key, + cache_entry_key (entry)); + } + if (error == 0) + { + error = + cache_entry_skip_or_load_header (&loader, load_header, + &(entry->flags), + &(entry->header_length), + entry->max_header, + cache_entry_header (entry)); + } + if (error == 0) + { + error = + cache_entry_skip_or_load_body (&loader, load_body, &(entry->flags), + &(entry->body_length), entry->max_body, + cache_entry_body (entry)); + } + if (error == 0) + { cache_entry_set_request_date (entry, &request_date); cache_entry_set_response_date (entry, &response_date); cache_entry_set_invalidated (entry, invalidated); @@ -436,6 +687,18 @@ disfluid_cache_entry_loader_read (void *context, void *buffer, size_t max) return read (*fdp, buffer, max); } +static int +disfluid_cache_entry_loader_lseek (void *context, size_t size) +{ + int *fdp = context; + off_t error = lseek (*fdp, size, SEEK_CUR); + if (error < 0) + { + return -1; + } + return 0; +} + static ssize_t disfluid_cache_entry_loader_fread (void *context, void *buffer, size_t max) { @@ -452,16 +715,34 @@ disfluid_cache_entry_loader_fread (void *context, void *buffer, size_t max) } static int -cache_entry_read (struct disfluid_cache_entry *entry, int fd) +disfluid_cache_entry_loader_fseek (void *context, size_t size) +{ + FILE *f = context; + off_t error = fseek (f, size, SEEK_CUR); + if (error < 0) + { + return -1; + } + return 0; +} + +static int +cache_entry_read (struct disfluid_cache_entry *entry, int load_key, + int load_header, int load_body, int fd) { int *fdp = &fd; - return cache_entry_load (entry, disfluid_cache_entry_loader_read, fdp); + return cache_entry_load (entry, load_key, load_header, load_body, + disfluid_cache_entry_loader_read, + disfluid_cache_entry_loader_lseek, fdp); } static int -cache_entry_fread (struct disfluid_cache_entry *entry, FILE * f) +cache_entry_fread (struct disfluid_cache_entry *entry, int load_key, + int load_header, int load_body, FILE * f) { - return cache_entry_load (entry, disfluid_cache_entry_loader_fread, f); + return cache_entry_load (entry, load_key, load_header, load_body, + disfluid_cache_entry_loader_fread, + disfluid_cache_entry_loader_fseek, f); } static void @@ -483,7 +764,17 @@ cache_entry_get_response_date (const struct disfluid_cache_entry *entry, static bool cache_entry_is_invalidated (const struct disfluid_cache_entry *entry) { - return entry->invalidated; + return (entry->flags & INVALIDATED) != 0; +} + +static void +cache_entry_is_loaded (const struct disfluid_cache_entry *entry, + bool *key_loaded, bool *header_loaded, + bool *body_loaded) +{ + *key_loaded = !(entry->flags & KEY_NOT_LOADED); + *header_loaded = !(entry->flags & HEADER_NOT_LOADED); + *body_loaded = !(entry->flags & BODY_NOT_LOADED); } struct disfluid_cache_entry_saver @@ -492,6 +783,66 @@ struct disfluid_cache_entry_saver void *context; }; +static size_t +cache_entry_careful_copy (size_t skip, size_t dest_max, char *dest, + size_t source_length, const char *source) +{ + size_t max = dest_max; + const char *relevant_source = NULL; + if (skip <= source_length) + { + relevant_source = &(source[skip]); + size_t max_source = source_length - skip; + max = max_source; + if (max > dest_max) + { + max = dest_max; + } + assert (skip + max <= source_length); + assert (max <= dest_max); + } + else + { + max = 0; + } + memcpy (dest, relevant_source, max); + if (max < dest_max) + { + dest[max] = '\0'; + } + return source_length; +} + +static size_t +cache_entry_get_key (const struct disfluid_cache_entry *entry, size_t start, + size_t max, char *key) +{ + return cache_entry_careful_copy (start, max, key, entry->key_length, + cache_entry_key ((struct + disfluid_cache_entry *) + entry)); +} + +static size_t +cache_entry_get_header (const struct disfluid_cache_entry *entry, + size_t start, size_t max, char *header) +{ + return cache_entry_careful_copy (start, max, header, entry->header_length, + cache_entry_header ((struct + disfluid_cache_entry + *) entry)); +} + +static size_t +cache_entry_get_body (const struct disfluid_cache_entry *entry, size_t start, + size_t max, char *body) +{ + return cache_entry_careful_copy (start, max, body, entry->body_length, + cache_entry_body ((struct + disfluid_cache_entry *) + entry)); +} + static int cache_entry_really_save_n (struct disfluid_cache_entry_saver *saver, size_t n, const uint8_t * data) @@ -559,6 +910,26 @@ cache_entry_save_flags (struct disfluid_cache_entry_saver *saver, } static int +cache_entry_save_section (struct disfluid_cache_entry_saver *saver, + size_t length, const char *section) +{ + uint8_t size[sizeof (length)] = { 0 }; + size_t size_n = length; + for (size_t i = sizeof (length); i-- > 0;) + { + size[i] = size_n % 256; + size_n /= 256; + } + int error = cache_entry_really_save_n (saver, sizeof (length), size); + if (error == 0) + { + error = + cache_entry_really_save_n (saver, length, (const uint8_t *) section); + } + return error; +} + +static int cache_entry_save (const struct disfluid_cache_entry *entry, ssize_t (*write_impl) (void *context, const void *buffer, size_t max_size), void *context) @@ -568,6 +939,10 @@ cache_entry_save (const struct disfluid_cache_entry *entry, .context = context }; int error = 0; + if (entry->flags & (KEY_NOT_LOADED | HEADER_NOT_LOADED | BODY_NOT_LOADED)) + { + error = -2; + } if (error == 0) { error = cache_entry_save_magic (&saver); @@ -582,7 +957,31 @@ cache_entry_save (const struct disfluid_cache_entry *entry, } if (error == 0) { - error = cache_entry_save_flags (&saver, entry->invalidated); + error = cache_entry_save_flags (&saver, !!(entry->flags & INVALIDATED)); + } + if (error == 0) + { + error = + cache_entry_save_section (&saver, entry->key_length, + cache_entry_key ((struct + disfluid_cache_entry *) + entry)); + } + if (error == 0) + { + error = + cache_entry_save_section (&saver, entry->header_length, + cache_entry_header ((struct + disfluid_cache_entry *) + entry)); + } + if (error == 0) + { + error = + cache_entry_save_section (&saver, entry->body_length, + cache_entry_body ((struct + disfluid_cache_entry *) + entry)); } return error; } diff --git a/src/libdisfluid/disfluid-tests.h b/src/libdisfluid/disfluid-tests.h index 6633872..df6d534 100644 --- a/src/libdisfluid/disfluid-tests.h +++ b/src/libdisfluid/disfluid-tests.h @@ -92,7 +92,7 @@ START_TEST (test_read_invalid_magic_number) { abort (); } - int error = cache_entry_read (entry, fd); + int error = cache_entry_read (entry, true, true, true, fd); cache_entry_free (entry); close (fd); ck_assert_int_eq (error, -2); @@ -104,13 +104,26 @@ END_TEST static inline void test_check_partial_situation (size_t n_partial) { - uint8_t data[16 + 12 + 12 + 1] = { 0 }; - memcpy (data, "disfluid c.entry", 16); - data[16 + 8 - 1] = 1; - data[16 + 12 - 1] = 2; - data[16 + 12 + 8 - 1] = 3; - data[16 + 12 + 12 - 1] = 4; - data[16 + 12 + 12 + 1 - 1] = 0x80; + const uint8_t data[] = { 'd', 'i', 's', 'f', 'l', 'u', 'i', 'd', + ' ', 'c', '.', 'e', 'n', 't', 'r', 'y', + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, + 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, + 128, + 0, 0, 0, 0, 0, 0, 0, 25, + 'G', 'E', 'T', ' ', 'h', 't', 't', 'p', + 's', ':', '/', '/', 'e', 'x', 'a', 'm', + 'p', 'l', 'e', '.', 'c', 'o', 'm', '\r', + '\n', + 0, 0, 0, 0, 0, 0, 0, 22, + 't', 'h', 'e', ' ', 'r', 'e', 's', 'p', + 'o', 'n', 's', 'e', ' ', 'h', 'e', 'a', + 'd', 'e', 'r', '.', '.', '.', + 0, 0, 0, 0, 0, 0, 0, 20, + 't', 'h', 'e', ' ', 'r', 'e', 's', 'p', + 'o', 'n', 's', 'e', ' ', 'b', 'o', 'd', + 'y', '.', '.', '.' + }; + assert (sizeof (data) == 132); /* The data has a request date of 1s + 2ns, response of 3s + 4ns, and is invalidated. */ assert (n_partial <= sizeof (data) / sizeof (data[0])); @@ -125,7 +138,7 @@ test_check_partial_situation (size_t n_partial) { abort (); } - int error = cache_entry_read (entry, fd); + int error = cache_entry_read (entry, 1, 1, 1, fd); if (n_partial < sizeof (data) / sizeof (data[0])) { ck_assert_int_eq (error, -3); @@ -137,11 +150,26 @@ test_check_partial_situation (size_t n_partial) cache_entry_get_request_date (entry, &request); cache_entry_get_response_date (entry, &response); bool invalidated = cache_entry_is_invalidated (entry); + char key[512 BYTES]; + char header[4 KILOBYTES]; + char body[4 KILOBYTES]; /* Do NOT allocate 2 megabytes on the + stack, valgrind finds it + offensive. */ ck_assert_int_eq (request.tv_sec, 1); ck_assert_int_eq (request.tv_nsec, 2); ck_assert_int_eq (response.tv_sec, 3); ck_assert_int_eq (response.tv_nsec, 4); ck_assert (invalidated); + ck_assert_int_eq (cache_entry_get_key (entry, 0, sizeof (key), key), + 25); + ck_assert_int_eq (cache_entry_get_header + (entry, 0, sizeof (header), header), 22); + ck_assert_int_eq (cache_entry_get_body (entry, 0, sizeof (body), body), + 20); + body[strlen ("the response body...")] = '\0'; + ck_assert_str_eq (key, "GET https://example.com\r\n"); + ck_assert_str_eq (header, "the response header..."); + ck_assert_str_eq (body, "the response body..."); } cache_entry_free (entry); close (fd); @@ -254,6 +282,36 @@ END_TEST /* *INDENT-ON* */ /* *INDENT-ON* */ +START_TEST (test_read_cache_file_partial_50) +/* *INDENT-ON* */ +{ + test_check_partial_situation (50); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* *INDENT-ON* */ +START_TEST (test_read_cache_file_partial_131) +/* *INDENT-ON* */ +{ + test_check_partial_situation (131); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* *INDENT-ON* */ +START_TEST (test_read_cache_file_partial_132) +/* *INDENT-ON* */ +{ + test_check_partial_situation (132); +} +/* *INDENT-OFF* */ +END_TEST +/* *INDENT-ON* */ + +/* *INDENT-ON* */ START_TEST (test_load_and_shrink) /* *INDENT-ON* */ { @@ -277,9 +335,7 @@ START_TEST (test_load_and_shrink) const size_t required_size = cache_entry_size (default_key_size, default_header_size, default_body_size); - const size_t required_alignment = - cache_entry_alignment (default_key_size, default_header_size, - default_body_size); + const size_t required_alignment = cache_entry_alignment (); entry = calloc (1, required_size); if (entry == NULL) { @@ -342,7 +398,7 @@ START_TEST (test_write_cache_entry) /* *INDENT-ON* */ { - uint8_t old_data[16 + 12 + 12 + 1] = { 0 }; + uint8_t old_data[16 + 12 + 12 + 1 + 8 + 8 + 8 + 1024] = { 0 }; memcpy (old_data, "disfluid c.entry", 16); old_data[16 + 8 - 1] = 1; old_data[16 + 12 - 1] = 2; @@ -372,10 +428,13 @@ START_TEST (test_write_cache_entry) cache_entry_set_request_date (entry, &request); cache_entry_set_response_date (entry, &response); cache_entry_set_invalidated (entry, false); + cache_entry_set_key (entry, "GET https://example.com\r\n"); + cache_entry_set_response_header (entry, "the response header..."); + cache_entry_set_response_body (entry, strlen ("the response body..."), + "the response body..."); int error = cache_entry_write (entry, fd); ck_assert_int_eq (error, 0); - uint8_t check_data[16 + 12 + 12 + 1]; - assert (sizeof (check_data) == sizeof (old_data)); + uint8_t check_data[16 + 12 + 12 + 1 + 8 + 8 + 8 + 25 + 22 + 20]; error = lseek (fd, 0, SEEK_SET); ck_assert_int_eq (error, 0); struct disfluid_cache_entry_loader read_loader = { @@ -387,12 +446,37 @@ START_TEST (test_write_cache_entry) (&read_loader, (sizeof (check_data) / sizeof (check_data[0])), check_data)); ck_assert_int_eq (check_error, 0); - ck_assert_int_eq (memcmp (check_data, "disfluid c.entry", 16), 0); - ck_assert_int_eq (check_data[16 + 8 - 1], 10); - ck_assert_int_eq (check_data[16 + 12 - 1], 11); - ck_assert_int_eq (check_data[16 + 12 + 8 - 1], 12); - ck_assert_int_eq (check_data[16 + 12 + 12 - 1], 13); - ck_assert_int_eq (check_data[16 + 12 + 12 + 1 - 1], 0); + static const uint8_t expected_data[] = + { 'd', 'i', 's', 'f', 'l', 'u', 'i', 'd', + ' ', 'c', '.', 'e', 'n', 't', 'r', 'y', + 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 11, + 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 13, + 0, + 0, 0, 0, 0, 0, 0, 0, 25, + 'G', 'E', 'T', ' ', 'h', 't', 't', 'p', + 's', ':', '/', '/', 'e', 'x', 'a', 'm', + 'p', 'l', 'e', '.', 'c', 'o', 'm', '\r', + '\n', + 0, 0, 0, 0, 0, 0, 0, 22, + 't', 'h', 'e', ' ', 'r', 'e', 's', 'p', + 'o', 'n', 's', 'e', ' ', 'h', 'e', 'a', + 'd', 'e', 'r', '.', '.', '.', + 0, 0, 0, 0, 0, 0, 0, 20, + 't', 'h', 'e', ' ', 'r', 'e', 's', 'p', + 'o', 'n', 's', 'e', ' ', 'b', 'o', 'd', + 'y', '.', '.', '.', + }; + ck_assert_int_eq (sizeof (expected_data), sizeof (check_data)); + for (size_t i = 0; i < sizeof (expected_data); i++) + { + if (check_data[i] != expected_data[i]) + { + fprintf (stderr, "%s:%d: %lu: %d vs %d.\n", __FILE__, __LINE__, i, + (int) check_data[i], (int) expected_data[i]); + } + } + ck_assert_int_eq (memcmp + (check_data, expected_data, sizeof (expected_data)), 0); close (fd); cache_entry_free (entry); } @@ -698,6 +782,9 @@ run_tests (size_t *n_tests, size_t *n_errors) tcase_add_test (cache_entry, test_read_cache_file_partial_37); tcase_add_test (cache_entry, test_read_cache_file_partial_40); tcase_add_test (cache_entry, test_read_cache_file_partial_41); + tcase_add_test (cache_entry, test_read_cache_file_partial_50); + tcase_add_test (cache_entry, test_read_cache_file_partial_131); + tcase_add_test (cache_entry, test_read_cache_file_partial_132); tcase_add_test (cache_entry, test_load_and_shrink); tcase_add_test (cache_entry, test_write_cache_entry); suite_add_tcase (suite, cache_entry); diff --git a/src/libdisfluid/main.c b/src/libdisfluid/main.c index 4d5b573..6b21295 100644 --- a/src/libdisfluid/main.c +++ b/src/libdisfluid/main.c @@ -124,10 +124,9 @@ disfluid_cache_entry_size (size_t max_key, size_t max_header, size_t max_body) } size_t -disfluid_cache_entry_alignment (size_t max_key, size_t max_header, - size_t max_body) +disfluid_cache_entry_alignment (void) { - return cache_entry_alignment (max_key, max_header, max_body); + return cache_entry_alignment (); } void @@ -198,6 +197,27 @@ disfluid_cache_entry_set_invalidated (struct disfluid_cache_entry *entry, cache_entry_set_invalidated (entry, invalidated); } +int +disfluid_cache_entry_set_key (struct disfluid_cache_entry *entry, + const char *key) +{ + return cache_entry_set_key (entry, key); +} + +int +disfluid_cache_entry_set_response_header (struct disfluid_cache_entry *entry, + const char *header) +{ + return cache_entry_set_response_header (entry, header); +} + +int +disfluid_cache_entry_set_response_body (struct disfluid_cache_entry *entry, + size_t body_length, const char *body) +{ + return cache_entry_set_response_body (entry, body_length, body); +} + void disfluid_cache_entry_get_request_date (const struct disfluid_cache_entry *entry, struct timespec *date) @@ -220,10 +240,14 @@ disfluid_cache_entry_is_invalidated (const struct disfluid_cache_entry *entry) int disfluid_cache_entry_load (struct disfluid_cache_entry *entry, + int load_key, + int load_header, + int load_body, ssize_t (*read_impl) (void *, void *, size_t), - void *context) + int (*skip) (void *, size_t), void *context) { - return cache_entry_load (entry, read_impl, context); + return cache_entry_load (entry, load_key, load_header, load_body, read_impl, + skip, context); } int @@ -235,15 +259,19 @@ disfluid_cache_entry_save (const struct disfluid_cache_entry *entry, } int -disfluid_cache_entry_read (struct disfluid_cache_entry *entry, int fd) +disfluid_cache_entry_read (struct disfluid_cache_entry *entry, + int read_key, + int read_header, int read_body, int fd) { - return cache_entry_read (entry, fd); + return cache_entry_read (entry, read_key, read_header, read_body, fd); } int -disfluid_cache_entry_fread (struct disfluid_cache_entry *entry, FILE * f) +disfluid_cache_entry_fread (struct disfluid_cache_entry *entry, + int read_key, + int read_header, int read_body, FILE * f) { - return cache_entry_fread (entry, f); + return cache_entry_fread (entry, read_key, read_header, read_body, f); } int |