/* mock_http_server
 *
 * Creates a mock high-concurrency webserver, which
 * simulates time-consuming requests.
 *
 * Every request pauses for between 0 and 20 seconds (average 10 seconds),
 * before returning 200 OK.
 *
 */
#include <assert.h>
#include <stdlib.h>
#include <time.h>
#include <evhttp.h>
#include <event.h>

#define HTTP_SERVER_ADDR   "127.0.0.1"
#define HTTP_SERVER_PORT   8080
#define HTTP_DELAY_MS      10000

struct event_base *evb;
struct evhttp *evh;

struct request_info {
    struct evhttp_request *request;
    struct event *timer;
};

void request_finish(int fd, short which, void *arg) {
    struct request_info *ri = (struct request_info*)arg;
    evtimer_del(ri->timer);
    evhttp_send_reply(ri->request, 200, "OK", NULL);
    free(ri);
}

void request_callback(struct evhttp_request *request, void *arg) {
    double jitter;
    long delay_ms;
    struct timeval tv;
    struct request_info *ri;
    ri = (struct request_info*)malloc(sizeof(struct request_info));
    ri->request = request;
    ri->timer = evtimer_new(evb, request_finish, (void*)ri);
    /* jitter is between -1.0 and 1.0 */
    jitter = 2.0*((double)rand())/(1.0 + RAND_MAX) - 1.0;
    delay_ms = 1 + (long)((1.0 + jitter)*HTTP_DELAY_MS);
    tv.tv_sec = delay_ms/1000;
    tv.tv_usec = (delay_ms % 1000)*1000;
    evtimer_add(ri->timer, &tv);
}
int main() {
    int rc;
    srand(time(NULL));
    evb = event_base_new();
    evh = evhttp_new(evb);
    rc = evhttp_bind_socket(evh, HTTP_SERVER_ADDR, HTTP_SERVER_PORT);
    assert(rc == 0);
    evhttp_set_gencb(evh, request_callback, NULL);
    event_base_dispatch(evb);
    return 0;
}
