140 lines
4.3 KiB
C
140 lines
4.3 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <haywire.h>
|
|
#include "uv.h"
|
|
#include "haywire.h"
|
|
#include "hw_string.h"
|
|
#include "khash.h"
|
|
#include "http_response_cache.h"
|
|
#include "http_server.h"
|
|
|
|
#define CRLF "\r\n"
|
|
KHASH_MAP_INIT_STR(string_hashmap, hw_string *)
|
|
|
|
//static uv_timer_t cache_invalidation_timer;
|
|
static uv_key_t thread_cache_key;
|
|
static uv_timer_t *cache_invalidation_timer;
|
|
|
|
void initialize_http_request_cache();
|
|
void free_http_request_cache();
|
|
void http_request_cache_timer(uv_timer_t *handle);
|
|
void create_cached_http_request(khash_t(string_hashmap) * http_request_cache, const char *http_status);
|
|
void set_cached_request(khash_t(string_hashmap) * http_request_cache, char *http_status, hw_string *cache_entry);
|
|
hw_string *get_cached_request(const char *http_status);
|
|
|
|
void initialize_http_request_cache() {
|
|
uv_key_create(&thread_cache_key);
|
|
}
|
|
|
|
void uninit_http_request_cache() {
|
|
if (cache_invalidation_timer) {
|
|
free(cache_invalidation_timer);
|
|
}
|
|
}
|
|
|
|
void http_request_cache_configure_listener(uv_loop_t *loop, uv_async_t *handle) {
|
|
cache_invalidation_timer = malloc(sizeof(uv_timer_t));
|
|
uv_timer_init(loop, cache_invalidation_timer);
|
|
uv_timer_start(cache_invalidation_timer, http_request_cache_timer, 500, 500);
|
|
|
|
if (handle != NULL) {
|
|
uv_unref((uv_handle_t *)cache_invalidation_timer);
|
|
}
|
|
}
|
|
|
|
void http_request_cache_timer(uv_timer_t *timer) {
|
|
khash_t(string_hashmap) *http_request_cache = uv_key_get(&thread_cache_key);
|
|
if (http_request_cache != NULL) {
|
|
free_http_request_cache(http_request_cache);
|
|
}
|
|
}
|
|
|
|
void free_http_request_cache(khash_t(string_hashmap) * http_request_cache) {
|
|
const char *k;
|
|
hw_string *v;
|
|
|
|
kh_foreach(http_request_cache, k, v, {
|
|
free((char *)k);
|
|
free(v->value);
|
|
free(v);
|
|
});
|
|
|
|
kh_destroy_string_hashmap(http_request_cache);
|
|
uv_key_set(&thread_cache_key, NULL);
|
|
}
|
|
|
|
void create_cached_http_request(khash_t(string_hashmap) * http_request_cache, const char *http_status) {
|
|
hw_string *cache_entry = malloc(sizeof(hw_string));
|
|
cache_entry->value = calloc(1024, 1);
|
|
cache_entry->length = 0;
|
|
hw_string status;
|
|
status.length = strlen(http_status);
|
|
status.value = http_status;
|
|
|
|
append_string(cache_entry, http_v1_1);
|
|
append_string(cache_entry, &status);
|
|
APPENDSTRING(cache_entry, CRLF);
|
|
append_string(cache_entry, server_name);
|
|
APPENDSTRING(cache_entry, CRLF);
|
|
|
|
// Add the current time.
|
|
time_t curtime;
|
|
time(&curtime);
|
|
char *current_time = ctime(&curtime);
|
|
hw_string current_datetime;
|
|
current_datetime.value = current_time;
|
|
current_datetime.length = strlen(current_time);
|
|
APPENDSTRING(cache_entry, "Date: ");
|
|
append_string(cache_entry, ¤t_datetime);
|
|
|
|
set_cached_request(http_request_cache, http_status, cache_entry);
|
|
}
|
|
|
|
void set_cached_request(khash_t(string_hashmap) * http_request_cache, char *http_status, hw_string *cache_entry) {
|
|
int ret;
|
|
khiter_t key;
|
|
|
|
key = kh_get(string_hashmap, http_request_cache, http_status);
|
|
if (key == kh_end(http_request_cache)) {
|
|
key = kh_put(string_hashmap, http_request_cache, dupstr(http_status), &ret);
|
|
kh_value(http_request_cache, key) = cache_entry;
|
|
}
|
|
}
|
|
|
|
hw_string *get_cached_request(const char *http_status) {
|
|
int is_missing = 0;
|
|
void *val;
|
|
khash_t(string_hashmap) * http_request_cache;
|
|
khiter_t key = 0;
|
|
|
|
/* This thread hasn't created a response cache so create one */
|
|
http_request_cache = uv_key_get(&thread_cache_key);
|
|
if (http_request_cache == NULL) {
|
|
http_request_cache = kh_init(string_hashmap);
|
|
uv_key_set(&thread_cache_key, http_request_cache);
|
|
}
|
|
|
|
key = kh_get(string_hashmap, http_request_cache, http_status);
|
|
if (key == kh_end(http_request_cache)) {
|
|
create_cached_http_request(http_request_cache, http_status);
|
|
} else {
|
|
val = kh_value(http_request_cache, key);
|
|
}
|
|
|
|
key = kh_get(string_hashmap, http_request_cache, http_status);
|
|
if (key == kh_end(http_request_cache)) {
|
|
is_missing = 1;
|
|
} else {
|
|
val = kh_value(http_request_cache, key);
|
|
is_missing = 0;
|
|
}
|
|
|
|
if (is_missing) {
|
|
return NULL;
|
|
}
|
|
|
|
return val;
|
|
}
|