summaryrefslogtreecommitdiff
path: root/module/storage.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/storage.c')
-rw-r--r--module/storage.c203
1 files changed, 153 insertions, 50 deletions
diff --git a/module/storage.c b/module/storage.c
index cb1085d..67863eb 100644
--- a/module/storage.c
+++ b/module/storage.c
@@ -21,12 +21,33 @@ struct sid_storage {
/* Book keeping for the records */
sid_nonce_t *records;
- size_t first;
+ size_t last;
size_t total;
size_t count;
- int wrapped;
};
+sid_storage_t*
+sid_storage_initialize (void *memory, size_t n_memory)
+{
+ sid_storage_t *storage;
+
+ if (!memory)
+ return NULL;
+ if (n_memory < sizeof (sid_storage_t) + (sizeof (sid_nonce_t) * 3))
+ return NULL;
+
+ storage = memory;
+ memset (storage, 0, sizeof (storage));
+
+ /* Note that we assume that it's all blank */
+ storage->records = (sid_nonce_t*)(storage + 1);
+ storage->total = (n_memory - sizeof (sid_storage_t)) / sizeof (sid_nonce_t);
+ storage->last = 0;
+ storage->count = 1;
+
+ return storage;
+}
+
int
sid_storage_store_assoc (sid_storage_t *store, const sid_assoc_t *assoc)
{
@@ -43,6 +64,7 @@ sid_storage_store_assoc (sid_storage_t *store, const sid_assoc_t *assoc)
strcpy (store->server, assoc->server ? assoc->server : "");
strcpy (store->handle, assoc->handle ? assoc->handle : "");
memcpy (store->secret, assoc->secret, assoc->n_secret);
+ store->n_secret = assoc->n_secret;
strcpy (store->type, assoc->type ? assoc->type : "");
store->expires = assoc->expires;
return 1;
@@ -99,17 +121,18 @@ nonce_put (sid_nonce_t rec, const char *nonce)
size_t len = strlen (nonce);
char *dst = (char*)rec;
+ assert (sizeof (sid_nonce_t) == 40);
+
/* If it's short enough, then just store. Fast */
- if (len < sizeof (rec)) {
+ if (len < 40) {
memcpy (dst, nonce, len);
- memset (dst + len, 0, sizeof (rec) - len);
+ memset (dst + len, 0, 40 - len);
/* Too long, need to compress into the record */
} else {
apr_sha1_ctx_t ctx;
- assert (sizeof (sid_nonce_t) == APR_SHA1_DIGESTSIZE + 20);
- assert (len > 20);
+ assert (APR_SHA1_DIGESTSIZE == 20);
/* The date prefix we just copy in */
memcpy (dst, nonce, 20);
@@ -122,39 +145,94 @@ nonce_put (sid_nonce_t rec, const char *nonce)
}
static void
-insert_nonce_record (sid_storage_t *store, sid_nonce_t rec, size_t at)
+bump_ring_forwards (sid_storage_t *store, size_t beg, size_t end)
{
- sid_nonce_t *records = store->records;
+ sid_nonce_t *records;
- assert (store->total > 2);
- assert (at < store->total);
- assert (at != store->first);
+ assert (store);
+ assert (end <= store->total);
- /* Insertion right after latest, either ancient, more likely top */
- if (at == store->first + 1 % store->total) {
- /* We can just copy in at this point */
+ if (beg == end)
+ return;
- /* Our ring has empty space in it, so always push forwards, but only until first */
- } else if (!store->wrapped) {
- memmove (records + at + 1, records + at, sizeof (rec) * (store->first - at));
- store->first += 1;
+ records = store->records;
+ assert (beg < store->total);
- /* Move data backwards to make space */
- } else if (store->first < at) {
- memmove (records + store->first + 2, records + store->first + 1,
- sizeof (rec) * (at - store->first));
+ /* Simple memmove forward? */
+ if (end < store->total && beg < end) {
+ memmove (store->records + beg + 1, store->records + beg,
+ (end - beg) * sizeof (sid_nonce_t));
- /* Move data forwards to make space simply */
+ /* We wrap, far more complex */
} else {
- memmove (records + at + 1, records + at, sizeof (rec) * (store->first - at - 1));
+ if (end < beg)
+ memmove (store->records + 1, store->records,
+ end * sizeof (sid_nonce_t));
+ memcpy (store->records, store->records + store->total - 1,
+ sizeof (sid_nonce_t));
+ memmove (store->records + beg + 1, store->records + beg,
+ (store->total - beg - 1) * sizeof (sid_nonce_t));
}
+}
- memcpy (records[at], rec, sizeof (rec));
- ++store->count;
+static void
+bump_ring_backwards (sid_storage_t *store, size_t beg, size_t end)
+{
+ sid_nonce_t *records;
+
+ assert (store);
+ assert (end <= store->total);
+
+ if (beg == end)
+ return;
+
+ records = store->records;
+ assert (beg < store->total);
+
+ /* Simple memmove backwards? */
+ if (beg > 0 && beg < end) {
+ memmove (store->records + beg - 1, store->records + beg,
+ (end - beg) * sizeof (sid_nonce_t));
- /* Track whether we have a full ring or not. */
- if (!store->wrapped && store->count > store->total)
- store->wrapped = 1;
+ /* We wrap, far more complex */
+ } else {
+ if (end < beg)
+ memmove (store->records + beg - 1, store->records + beg,
+ (store->total - beg) * sizeof (sid_nonce_t));
+ memcpy (store->records + store->total - 1, store->records,
+ sizeof (sid_nonce_t));
+ memmove (store->records, store->records + 1,
+ (end - 1) * sizeof (sid_nonce_t));
+ }
+}
+
+static void
+insert_nonce_ring (sid_storage_t *store, sid_nonce_t rec, size_t idx)
+{
+ sid_nonce_t *records = store->records;
+ size_t off, top, bottom;
+
+ assert (store->total > 2);
+ assert (idx < store->total);
+
+ /* Calculate the distance on either side of last */
+ bottom = store->last;
+ top = store->last + store->total;
+ off = idx;
+ if (off <= bottom)
+ off += store->total;
+
+ /* Backwards move */
+ if (off - bottom < top - off) {
+ bump_ring_backwards (store, (store->last + 2) % store->total, idx);
+ memcpy (records + idx - 1, rec, sizeof (sid_nonce_t));
+
+ /* Forwards or no move */
+ } else {
+ bump_ring_forwards (store, idx, (store->last + 1) % store->total);
+ memcpy (records + idx, rec, sizeof (sid_nonce_t));
+ store->last = (store->last + 1) % store->total;
+ }
}
int
@@ -162,45 +240,70 @@ sid_storage_check_nonce (sid_storage_t *store, const char *server, const char *n
{
sid_nonce_t *records;
sid_nonce_t rec;
- size_t at, lower, upper, mid;
+ size_t idx, lower, upper, mid;
int res;
assert (store);
assert (nonce);
assert (store->records);
- assert (store->first < store->total);
+ assert (store->last < store->total);
nonce_put (rec, nonce);
records = store->records;
+
/* Best case scenario, new nonce is higher than our latest one */
- res = nonce_compare (rec, records[store->first]);
+ res = nonce_compare (rec, records[store->last]);
/* Was the last nonce */
if (res == 0) {
return 1;
/* Newer than anything, push on top */
- } else if (res < 0) {
- at = (store->first + 1) % store->total;
- insert_nonce_record (store, rec, at);
- store->first = at;
- return 0;
- }
+ } else if (res > 0) {
+ store->last = (store->last + 1) % store->total;
+ memcpy (records + store->last, rec, sizeof (sid_nonce_t));
+
+ } else {
- /* Do a binary search for the item */
- for (lower = 0, upper = store->total; lower < upper; ) {
- mid = lower + ((upper - lower) / 2); // Note: not (low + high) / 2 !!
- at = at + store->first % store->total;
- res = nonce_compare (rec, records[at]);
- if (res == 0)
- return 1; /* Have the nonce */
- else if (res > 0)
- lower = mid + 1;
- else
- upper = mid;
+ /* Check if it's before our last one, assume expired if so */
+ idx = (store->last + 1) % store->total;
+ res = nonce_compare (rec, records[idx]);
+ if (res < 0) {
+ return 1;
+
+ /* Do a binary search for the item */
+ } else {
+ lower = 0;
+ if (store->count < store->total)
+ lower = store->total - store->count;
+ upper = store->total;
+ while (lower < upper) {
+ mid = lower + ((upper - lower) / 2); // Note: not (low + high) / 2 !!
+ idx = (store->last + mid) % store->total;
+ res = nonce_compare (rec, records[idx]);
+ if (res == 0)
+ return 1; /* Have the nonce */
+ else if (res > 0)
+ lower = mid + 1;
+ else
+ upper = mid;
+ }
+
+ idx = (store->last + upper) % store->total;
+ insert_nonce_ring (store, rec, idx);
+ }
}
- insert_nonce_record (store, rec, at);
+ ++store->count;
return 0; /* Didn't find nonce */
}
+
+size_t
+sid_storage_nonce_capacity (sid_storage_t *storage)
+{
+ assert (storage);
+ return storage->total;
+}
+
+