summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVivien Kraus <vivien@planete-kraus.eu>2023-03-21 20:51:00 +0100
committerVivien Kraus <vivien@planete-kraus.eu>2023-03-25 13:24:39 +0100
commit2c04502589876dc4c19bdbff4426757571ac76b0 (patch)
tree302bbb198829c00b51a64898cb6510c3da43d955
parentb7a76711ed9898dca90b91f87c5dcbd49be9553e (diff)
Optionally store a key, response header and body in a cache entry
-rw-r--r--bootstrap.conf1
-rw-r--r--doc/disfluid.texi161
-rw-r--r--include/disfluid/cache_entry.h49
-rw-r--r--src/libdisfluid/disfluid-cache-entry.h527
-rw-r--r--src/libdisfluid/disfluid-tests.h129
-rw-r--r--src/libdisfluid/main.c46
6 files changed, 812 insertions, 101 deletions
diff --git a/bootstrap.conf b/bootstrap.conf
index da85715..b708257 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -27,6 +27,7 @@ copy-file-range
do-release-commit-and-tag
errno
fclose
+flexmember
free-posix
ftruncate
gettext-h
diff --git a/doc/disfluid.texi b/doc/disfluid.texi
index be1d82f..bf66908 100644
--- a/doc/disfluid.texi
+++ b/doc/disfluid.texi
@@ -7,7 +7,7 @@
@settitle Demanding Interoperability to Strengthen the Free (Libre) Web: Introducing Disfluid
@c %**end of header
-@set UPDATED 20 March 2023
+@set UPDATED 21 March 2023
@set UPDATED-MONTH March 2023
@include version_number.texi
@@ -219,4 +219,163 @@ NUL-terminated, and the value @code{-2} is returned. Otherwise,
@code{0} is returned.
@end deftypefun
+@deftp struct disfluid_cache_entry
+A structure that can hold everything related to a cache entry. The
+specific layout is hidden, but the overall size and alignment can be
+queried at run-time.
+@end deftp
+
+@deftypefun size_t disfluid_cache_entry_size (size_t @var{max_key}, size_t @var{max_header}, size_t @var{max_body})
+Return the size to allocate for a cache entry that can hold at most
+@var{max_key} bytes of the key (method, URL and varied header values),
+at most @var{max_header} for the response header, and at most
+@var{max_body} for the response body. Do not hesitate to demand server
+to send terse responses to you. 512 bytes for the key, 4 kB for the
+header, and 2 MB for the body should be more than enough for proper
+cache handling.
+
+This function is a constant function according to GCC: its output only
+depends on the three inputs, and it is not allowed to read global
+data. The compiler is free to reuse the same value without callig the
+function again. Define the @code{ATTRIBUTE_CONST} macro to the syntax
+for function attributes for your compiler. If you use gnulib, use the
+@samp{attribute} module and include @code{attribute.h} before
+@code{disfluid.h} to use this optimization.
+@end deftypefun
+
+@deftypefun size_t disfluid_cache_entry_alignment (void)
+Return the proper alignment for a cache entry. This function is
+constant too.
+@end deftypefun
+
+@deftypefun size_t disfluid_cache_entry_init (struct disfluid_cache_entry *@var{entry}, size_t @var{max_key}, size_t @var{max_header}, size_t @var{max_body})
+Initialize the @var{entry}, that must be aligned properly, and
+allocated with an appropriate size, such as given by
+@code{disfluid_cache_entry_size}.
+@end deftypefun
+
+@deftypefun void disfluid_cache_entry_minimum_size (const struct disfluid_cache_entry *@var{entry}, size_t *@var{min_key}, size_t *@var{min_header}, size_t *@var{min_body})
+Set @var{min_key}, @var{min_header} and @var{min_body} to the minimum
+sizes that should be allocated to hold the key, header and body of
+@var{entry}.
+@end deftypefun
+
+@deftypefun int disfluid_cache_entry_copy (struct disfluid_cache_entry *@var{dest}, const struct disfluid_cache_entry *@var{src})
+Copy @var{src} to @var{dest}. If one of the @var{dest} limits is too
+short, return a negative error code. Otherwise, return 0.
+
+@table @code
+@item -1, -3, -5, -7
+indicates that the key does not fit in @var{dest};
+@item -2, -3, -6, -7
+indicates that the response header does not fit in @var{dest};
+@item -4, -5, -6, -7
+indicates that the response body does not fit in @var{dest}.
+@end table
+@end deftypefun
+
+@deftypefun {struct disfluid_cache_entry *} disfluid_cache_entry_alloc (size_t @var{max_key}, size_t @var{max_header}, size_t @var{max_body})
+@deftypefunx {struct disfluid_cache_entry *} disfluid_cache_entry_dup (const struct disfluid_cache_entry *@var{src})
+Allocate a new cache entry with the libc standard
+allocator. @code{disfluid_cache_entry_dup} allocates the same limits
+as those of @var{src}.
+@end deftypefun
+
+@deftypefun void disfluid_cache_entry_free (struct disfluid_cache_entry *@var{entry})
+Free a cache entry allocated with the standard libc allocator.
+@end deftypefun
+
+To make memory allocation a bit safer, you can use the
+@code{DISFLUID_CACHE_ENTRY_ALLOC (@var{ptr}, @var{max_key},
+@var{max_header}, @var{max_body})} and
+@code{DISFLUID_CACHE_ENTRY_FREE(@var{ptr})} macros as:
+
+@example
+struct disfluid_cache_entry *entry;
+if (DISFLUID_CACHE_ENTRY_ALLOC (entry, 512, 4096, 2 * 1024 * 1024) < 0)
+ @{
+ /* Handle memory allocation failure */
+ @}
+else
+ @{
+ /* Do something with entry… */
+ @}
+DISFLUID_CACHE_ENTRY_FREE (entry);
+/* entry is set to NULL */
+assert (entry == NULL);
+@end example
+
+@deftypefun void disfluid_cache_entry_set_request_date (struct disfluid_cache_entry *@var{entry}, const struct timespec *@var{request_date})
+@deftypefunx void disfluid_cache_entry_set_response_date (struct disfluid_cache_entry *@var{entry}, const struct timespec *@var{response_date})
+@deftypefunx void disfluid_cache_entry_set_invalidated (struct disfluid_cache_entry *@var{entry}, int @var{invalidated})
+@deftypefunx void disfluid_cache_entry_invalidate (struct disfluid_cache_entry *@var{entry})
+Manage the metadata associated with @var{entry}.
+@end deftypefun
+
+@deftypefun int disfluid_cache_entry_set_key (struct disfluid_cache_entry *@var{entry}, const char *@var{key})
+@deftypefunx int disfluid_cache_entry_set_header (struct disfluid_cache_entry *@var{entry}, const char *@var{header})
+@deftypefunx int disfluid_cache_entry_set_body (struct disfluid_cache_entry *@var{entry}, size_t @var{body_length}, const char *@var{body})
+Try and set the relevant cache entry section in @var{entry}. If the
+respective limit is too short, return a negative error
+code. Otherwise, return 0.
+@end deftypefun
+
+@deftypefun void disfluid_cache_entry_get_request_date (const struct disfluid_cache_entry *@var{entry}, struct timespec *@var{request_date})
+@deftypefunx void disfluid_cache_entry_get_response_date (const struct disfluid_cache_entry *@var{entry}, struct timespec *@var{response_date})
+@deftypefunx int disfluid_cache_entry_is_invalidated (const struct disfluid_cache_entry *@var{entry})
+Query the metadata of @var{entry}.
+@end deftypefun
+
+@deftypefun size_t disfluid_cache_entry_get_key (const struct disfluid_cache_entry *@var{entry}, size_t @var{start}, size_t @var{max}, char *@var{dst})
+@deftypefunx size_t disfluid_cache_entry_get_header (const struct disfluid_cache_entry *@var{entry}, size_t @var{start}, size_t @var{max}, char *@var{dst})
+@deftypefunx size_t disfluid_cache_entry_get_body (const struct disfluid_cache_entry *@var{entry}, size_t @var{start}, size_t @var{max}, char *@var{dst})
+Ignore the first @var{start} bytes, and copy the next bytes of the
+relevant section in @var{entry}, up to @var{max}, to @var{dst}. Return
+the total length of the section. If there is more room allocated, make
+sure that @var{dst} is NUL-terminated.
+@end deftypefun
+
+@deftypefun int disfluid_cache_entry_load (struct disfluid_cache_entry *@var{entry}, int @var{load_key}, int @var{load_header}, int @var{load_body}, ssize_t (*@var{read_impl}) (void *, void *, size_t), int (*@var{skip}) (void *, size_t), void *@var{context})
+@deftypefunx int disfluid_cache_entry_read (struct disfluid_cache_entry *@var{entry}, int @var{load_key}, int @var{load_header}, int @var{load_body}, int @var{fd})
+@deftypefunx int disfluid_cache_entry_fread (struct disfluid_cache_entry *@var{entry}, int @var{load_key}, int @var{load_header}, int @var{load_body}, FILE *@var{handle})
+Load a file to set up @var{entry}. If @var{load_key} (respectively,
+@var{load_header} and @var{load_body}) is a strictly positive value,
+then attempt to read the key (respectively, the header and body). If
+it is 0, then skip it, but keep the previously loaded value. If it is
+negative, then erase the value. The specific
+@code{disfluid_cache_entry_read} and @code{disfluid_cache_entry_fread}
+use a file descriptor and a stream file handle respectively, instead
+of custom callbacks.
+
+@code{disfluid_cache_entry_load} uses custom callbacks to read the
+file. The file is passed as @var{context}, and during the calls to
+@var{read_impl} and @var{skip}, it is bound to the first argument. The
+second argument of @var{read_impl} is bound to a buffer where to read
+the bytes. The last argument is bound to the read request size, in
+bytes.
+
+@var{read_impl} is supposed to return a negative value if a file
+system failure occurs, 0 if the file is at end, or a value at most
+equal to the read request, and set the bytes in the buffer
+accordingly. @var{skip} is supposed to return 0 on success and advance
+the file pointer by the request size, or return a negative error code.
+
+The loading functions return 0 on success, -1 in case of a file system
+error, -2 if the file is invalid, -3 if it is incomplete, -4 if the
+key is too large, -5 if the header is too large, -6 if the body is too
+large.
+@end deftypefun
+
+@deftypefun int disfluid_cache_entry_save (const struct disfluid_cache_entry *@var{entry}, ssize_t (*@var{write_impl}) (void *, const void *, size_t), void *@var{context})
+@deftypefunx int disfluid_cache_entry_write (const struct disfluid_cache_entry *@var{entry}, int @var{fd})
+@deftypefunx int disfluid_cache_entry_fwrite (const struct disfluid_cache_entry *@var{entry}, FILE *@var{handle})
+Save @var{entry} to a file. Return 0 on success, -1 if writing to the
+file raised an error, -2 if the key, header or body is unset in
+@var{entry}. @var{write_impl} is called with @var{context} bound to
+the first argument, an array of bytes to write as the second, and the
+array length as the third. It should return a negative value to signal
+an error, or a value at most the write request length, and write the
+corresponding bytes in the request to file.
+@end deftypefun
+
@bye
diff --git a/include/disfluid/cache_entry.h b/include/disfluid/cache_entry.h
index fcfb43f..6004932 100644
--- a/include/disfluid/cache_entry.h
+++ b/include/disfluid/cache_entry.h
@@ -15,8 +15,7 @@ extern "C"
size_t max_header, size_t max_body);
LIBDISFLUID_API LIBDISFLUID_CONST extern size_t
- disfluid_cache_entry_alignment (size_t max_key,
- size_t max_header, size_t max_body);
+ disfluid_cache_entry_alignment (void);
LIBDISFLUID_API extern void
disfluid_cache_entry_init (struct disfluid_cache_entry *entry,
@@ -67,6 +66,20 @@ extern "C"
LIBDISFLUID_API extern void
disfluid_cache_entry_invalidate (struct disfluid_cache_entry *entry);
+ LIBDISFLUID_API extern int
+ disfluid_cache_entry_set_key (struct disfluid_cache_entry *entry,
+ const char *key);
+
+ LIBDISFLUID_API extern int
+ disfluid_cache_entry_set_response_header (struct disfluid_cache_entry
+ *entry, const char *header);
+
+ LIBDISFLUID_API extern int
+ disfluid_cache_entry_set_response_body (struct disfluid_cache_entry
+ *entry,
+ size_t body_length,
+ const char *body);
+
LIBDISFLUID_API extern void
disfluid_cache_entry_get_request_date (const struct disfluid_cache_entry
*entry, struct timespec *date);
@@ -79,19 +92,39 @@ extern "C"
disfluid_cache_entry_is_invalidated (const struct disfluid_cache_entry
*entry);
+ LIBDISFLUID_API extern size_t
+ disfluid_cache_entry_get_key (const struct disfluid_cache_entry *entry,
+ size_t start, size_t max, char *key);
+
+ LIBDISFLUID_API extern size_t
+ disfluid_cache_entry_get_header (const struct disfluid_cache_entry *entry,
+ size_t start, size_t max, char *header);
+
+ LIBDISFLUID_API extern size_t
+ disfluid_cache_entry_get_body (const struct disfluid_cache_entry *entry,
+ size_t start, size_t max, char *body);
+
LIBDISFLUID_NODISCARD LIBDISFLUID_API extern int
disfluid_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),
+ int (*skip) (void *context, size_t size),
void *context);
LIBDISFLUID_NODISCARD LIBDISFLUID_FD_ARG_READ_2 LIBDISFLUID_API
extern int disfluid_cache_entry_read (struct disfluid_cache_entry *entry,
- int fd);
+ int load_key,
+ int load_header,
+ int load_body, int fd);
LIBDISFLUID_NODISCARD LIBDISFLUID_API extern int
- disfluid_cache_entry_fread (struct disfluid_cache_entry *entry, FILE * f);
+ disfluid_cache_entry_fread (struct disfluid_cache_entry *entry,
+ int load_key,
+ int load_header, int load_body, FILE * f);
LIBDISFLUID_NODISCARD LIBDISFLUID_API extern int
disfluid_cache_entry_save (const struct disfluid_cache_entry *entry,
@@ -108,8 +141,12 @@ extern "C"
disfluid_cache_entry_fwrite (const struct disfluid_cache_entry *entry,
FILE * f);
-# define DISFLUID_CACHE_ENTRY_ALLOC(ptr, max_header, max_body) \
- (ptr = disfluid_cache_entry_alloc (max_header, max_body), \
+# define DISFLUID_CACHE_ENTRY_ALLOC(ptr, max_key, max_header, max_body) \
+ (ptr = disfluid_cache_entry_alloc (max_key, max_header, max_body), \
+ assert (sizeof (size_t) == sizeof (struct disfluid_cache_entry *)), \
+ size_t offset, \
+ memcpy (&offset, &ptr, sizeof (size_t)), \
+ assert (offset % disfluid_cache_entry_alignment () == 0), \
ptr == NULL ? -1 : 0)
# define DISFLUID_CACHE_ENTRY_FREE(ptr) \
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