<commit_before>#include "server.h"

static int request_handle_uri(request_t* r);
static int request_handle_request_line(request_t* r);
static int request_handle_headers(request_t* r);
static int request_handle_body(request_t* r);
static int header_handle_generic(request_t* r, int offset);
static int header_handle_connection(request_t* r, int offset);
static int header_handle_t_encoding(request_t* r, int offset);
static int header_handle_content_length(request_t* r, int offset);
static int header_handle_host(request_t* r, int offset);
static int header_handle_accept(request_t* r, int offset);
static int header_handle_if_modified_since(request_t* r, int offset);
//static int request_process_headers(request_t* r);

typedef struct {
    string_t name;
    header_val_t val;
} header_nv_t;

#define HEADER_PAIR(name, processor)    \
    {STRING_INIT(#name), {offsetof(request_headers_t, name), processor}}
    
static header_nv_t header_tb[] = {
    HEADER_PAIR(cache_control, header_handle_generic),
    HEADER_PAIR(connection, header_handle_connection),
    HEADER_PAIR(date, header_handle_generic),
    HEADER_PAIR(pragma, header_handle_generic),
    HEADER_PAIR(trailer, header_handle_generic),
    HEADER_PAIR(transfer_encoding, header_handle_t_encoding),
    HEADER_PAIR(upgrade, header_handle_generic),
    HEADER_PAIR(via, header_handle_generic),
    HEADER_PAIR(warning, header_handle_generic),
    HEADER_PAIR(allow, header_handle_generic),
    HEADER_PAIR(content_encoding, header_handle_generic),
    HEADER_PAIR(content_language, header_handle_generic),
    HEADER_PAIR(content_length, header_handle_content_length),
    HEADER_PAIR(content_location, header_handle_generic),
    HEADER_PAIR(content_md5, header_handle_generic),
    HEADER_PAIR(content_range, header_handle_generic),
    HEADER_PAIR(content_type, header_handle_generic),
    HEADER_PAIR(expires, header_handle_generic),
    HEADER_PAIR(last_modified, header_handle_generic),
    
    HEADER_PAIR(accept, header_handle_accept),
    HEADER_PAIR(accept_charset, header_handle_generic),
    HEADER_PAIR(accept_encoding, header_handle_generic),
    HEADER_PAIR(authorization, header_handle_generic),
    HEADER_PAIR(cookie, header_handle_generic),
    HEADER_PAIR(expect, header_handle_generic),
    HEADER_PAIR(from, header_handle_generic),
    HEADER_PAIR(host, header_handle_host),
    HEADER_PAIR(if_match, header_handle_generic),
    HEADER_PAIR(if_modified_since, header_handle_if_modified_since),
    HEADER_PAIR(if_none_match, header_handle_generic),
    HEADER_PAIR(if_range, header_handle_generic),
    HEADER_PAIR(if_unmodified_since, header_handle_generic),
    HEADER_PAIR(max_forwards, header_handle_generic),
    HEADER_PAIR(proxy_authorization, header_handle_generic),
    HEADER_PAIR(range, header_handle_generic),
    HEADER_PAIR(referer, header_handle_generic),
    HEADER_PAIR(te, header_handle_generic),
    HEADER_PAIR(user_agent, header_handle_generic),
};

#undef HEADER_PAIR

#define HEADER_MAP_SIZE     (131)
static map_slot_t header_map_data[2 * HEADER_MAP_SIZE];
static map_t header_map = {
    .size = HEADER_MAP_SIZE,
    .max_size = 2 * HEADER_MAP_SIZE,
    .data = header_map_data,
    .cur = header_map_data + HEADER_MAP_SIZE
};

void header_map_init(void) {
    int n = sizeof(header_tb) / sizeof(header_tb[0]);
    for (int i = 0; i < n; ++i) {
        map_val_t val;
        val.header = header_tb[i].val;
        map_put(&header_map, &header_tb[i].name, &val);
    }
}

static inline void uri_init(uri_t* uri) {
    memset(uri, 0, sizeof(uri_t));
    uri->state = URI_S_BEGIN;
}

/*
 * Request
 */
void request_init(request_t* r, connection_t* c) {
    r->method = M_GET;    // Any value is ok
    r->version.major = 0;
    r->version.minor = 0;

    memset(&r->headers, 0, sizeof(r->headers));
    list_init(&r->accepts, &accept_pool);
    
    r->state = RL_S_BEGIN;
    string_init(&r->request_line);
    string_init(&r->header_name);
    string_init(&r->header_value);
    uri_init(&r->uri);
    string_init(&r->host);
    r->port = 80;
    
    r->stage = RS_REQUEST_LINE;
     
    r->discard_body = false;
    r->body_done = false;
    r->done = false;
    r->response_done = false;
    r->keep_alive = false;

    r->t_encoding = TE_IDENTITY;
    r->content_length = -1;
    r->body_received = 0;
    
    buffer_init(&r->rb);
    buffer_init(&r->sb);
    r->c = c;
    r->uc = NULL;
    r->in_handler = request_handle_request_line;
    r->out_handler = send_response_buffer;

    r->status = 200;
    r->resource_fd = -1;
    r->resource_len = 0;
}

void request_clear(request_t* r) {
    connection_t* c = r->c;
    connection_t* uc = r->uc;
    request_init(r, c);
    r->c = c;
    r->uc = uc;
}

void request_release(request_t* r) {
    // TODO(wgtdkp): release dynamic allocated resource
    // TODO(wgtdkp): ther won't by any dynamic allocated resource!!!
}

/*
 * Send recived data to backend
 * Return:
 *  OK: send all data in buffer
 *  AGAIN: send partial data
 *  ERROR: error occurred, the upstream connection must be closed
 */
int handle_pass(connection_t* uc) {
    request_t* r = uc->r;
    buffer_t* b = &r->rb;
    int err = buffer_send(b, uc->fd);
    if (err == OK) {
        // Remove the EPOLLOUT event of upstream side
        // Done send all data
        buffer_clear(b);
        connection_enable_in(r->c);
        connection_disable_out(uc);
    } else if (err == ERROR) {
        // The connection has been closed by peer
        response_build_err(r, 503);
    }
    return err;
}

/*
 * The upstream connection is closed every response finished
 * Return:
 *  OK, ERROR: the upstream connection must be closed
 *  AGAIN:
 */
int handle_upstream(connection_t* uc) {
    request_t* r = uc->r;
    buffer_t* b = &r->sb;
    int err = buffer_recv(b, uc->fd);
    if (err == OK) {
        // The connection has been closed by peer
        return ERROR;
    } else if (err == ERROR) {
        // Error in backend
        response_build_err(r, 503);
        return ERROR;
    } else if (buffer_full(b)) {
        //connection_disable_in(uc);
    }
    connection_enable_out(r->c);
    return err;
}

int send_response_buffer(request_t* r) {
    connection_t* c= r->c;
    buffer_t* b = &r->sb;
    int err = buffer_send(b, c->fd);<commit_msg>fix bug: issue 9<commit_after>#include "server.h"

static int request_handle_uri(request_t* r);
static int request_handle_request_line(request_t* r);
static int request_handle_headers(request_t* r);
static int request_handle_body(request_t* r);
static int header_handle_generic(request_t* r, int offset);
static int header_handle_connection(request_t* r, int offset);
static int header_handle_t_encoding(request_t* r, int offset);
static int header_handle_content_length(request_t* r, int offset);
static int header_handle_host(request_t* r, int offset);
static int header_handle_accept(request_t* r, int offset);
static int header_handle_if_modified_since(request_t* r, int offset);
//static int request_process_headers(request_t* r);

typedef struct {
    string_t name;
    header_val_t val;
} header_nv_t;

#define HEADER_PAIR(name, processor)    \
    {STRING_INIT(#name), {offsetof(request_headers_t, name), processor}}
    
static header_nv_t header_tb[] = {
    HEADER_PAIR(cache_control, header_handle_generic),
    HEADER_PAIR(connection, header_handle_connection),
    HEADER_PAIR(date, header_handle_generic),
    HEADER_PAIR(pragma, header_handle_generic),
    HEADER_PAIR(trailer, header_handle_generic),
    HEADER_PAIR(transfer_encoding, header_handle_t_encoding),
    HEADER_PAIR(upgrade, header_handle_generic),
    HEADER_PAIR(via, header_handle_generic),
    HEADER_PAIR(warning, header_handle_generic),
    HEADER_PAIR(allow, header_handle_generic),
    HEADER_PAIR(content_encoding, header_handle_generic),
    HEADER_PAIR(content_language, header_handle_generic),
    HEADER_PAIR(content_length, header_handle_content_length),
    HEADER_PAIR(content_location, header_handle_generic),
    HEADER_PAIR(content_md5, header_handle_generic),
    HEADER_PAIR(content_range, header_handle_generic),
    HEADER_PAIR(content_type, header_handle_generic),
    HEADER_PAIR(expires, header_handle_generic),
    HEADER_PAIR(last_modified, header_handle_generic),
    
    HEADER_PAIR(accept, header_handle_accept),
    HEADER_PAIR(accept_charset, header_handle_generic),
    HEADER_PAIR(accept_encoding, header_handle_generic),
    HEADER_PAIR(authorization, header_handle_generic),
    HEADER_PAIR(cookie, header_handle_generic),
    HEADER_PAIR(expect, header_handle_generic),
    HEADER_PAIR(from, header_handle_generic),
    HEADER_PAIR(host, header_handle_host),
    HEADER_PAIR(if_match, header_handle_generic),
    HEADER_PAIR(if_modified_since, header_handle_if_modified_since),
    HEADER_PAIR(if_none_match, header_handle_generic),
    HEADER_PAIR(if_range, header_handle_generic),
    HEADER_PAIR(if_unmodified_since, header_handle_generic),
    HEADER_PAIR(max_forwards, header_handle_generic),
    HEADER_PAIR(proxy_authorization, header_handle_generic),
    HEADER_PAIR(range, header_handle_generic),
    HEADER_PAIR(referer, header_handle_generic),
    HEADER_PAIR(te, header_handle_generic),
    HEADER_PAIR(user_agent, header_handle_generic),
};

#undef HEADER_PAIR

#define HEADER_MAP_SIZE     (131)
static map_slot_t header_map_data[2 * HEADER_MAP_SIZE];
static map_t header_map = {
    .size = HEADER_MAP_SIZE,
    .max_size = 2 * HEADER_MAP_SIZE,
    .data = header_map_data,
    .cur = header_map_data + HEADER_MAP_SIZE
};

void header_map_init(void) {
    int n = sizeof(header_tb) / sizeof(header_tb[0]);
    for (int i = 0; i < n; ++i) {
        map_val_t val;
        val.header = header_tb[i].val;
        map_put(&header_map, &header_tb[i].name, &val);
    }
}

static inline void uri_init(uri_t* uri) {
    memset(uri, 0, sizeof(uri_t));
    uri->state = URI_S_BEGIN;
}

/*
 * Request
 */
void request_init(request_t* r, connection_t* c) {
    r->method = M_GET;    // Any value is ok
    r->version.major = 0;
    r->version.minor = 0;

    memset(&r->headers, 0, sizeof(r->headers));
    list_init(&r->accepts, &accept_pool);
    
    r->state = RL_S_BEGIN;
    string_init(&r->request_line);
    string_init(&r->header_name);
    string_init(&r->header_value);
    uri_init(&r->uri);
    string_init(&r->host);
    r->port = 80;
    
    r->stage = RS_REQUEST_LINE;
     
    r->discard_body = false;
    r->body_done = false;
    r->done = false;
    r->response_done = false;
    r->keep_alive = false;

    r->t_encoding = TE_IDENTITY;
    r->content_length = -1;
    r->body_received = 0;
    
    buffer_init(&r->rb);
    buffer_init(&r->sb);
    r->c = c;
    r->uc = NULL;
    r->in_handler = request_handle_request_line;
    r->out_handler = send_response_buffer;

    r->status = 200;
    r->resource_fd = -1;
    r->resource_len = 0;
}

void request_clear(request_t* r) {
    connection_t* c = r->c;
    connection_t* uc = r->uc;
    request_init(r, c);
    r->c = c;
    r->uc = uc;
}

void request_release(request_t* r) {
    // TODO(wgtdkp): release dynamic allocated resource
    // TODO(wgtdkp): ther won't by any dynamic allocated resource!!!
}

/*
 * Send recived data to backend
 * Return:
 *  OK: send all data in buffer
 *  AGAIN: send partial data
 *  ERROR: error occurred, the upstream connection must be closed
 */
int handle_pass(connection_t* uc) {
    request_t* r = uc->r;
    buffer_t* b = &r->rb;
    int err = buffer_send(b, uc->fd);
    if (err == OK) {
        // Remove the EPOLLOUT event of upstream side
        // Done send all data
        buffer_clear(b);
        connection_enable_in(r->c);
        connection_disable_out(uc);
    } else if (err == ERROR) {
        // The connection has been closed by peer
        response_build_err(r, 503);
    }
    return err;
}

/*
 * The upstream connection is closed every response finished
 * Return:
 *  OK, ERROR: the upstream connection must be closed
 *  AGAIN:
 */
int handle_upstream(connection_t* uc) {
    request_t* r = uc->r;
    buffer_t* b = &r->sb;
    int err = buffer_recv(b, uc->fd);

    connection_enable_out(r->c);
    if (err == OK) {
        // The connection has been closed by peer
        return ERROR;
    } else if (err == ERROR) {
        // Error in backend
        response_build_err(r, 503);
        return ERROR;
    } else if (buffer_full(b)) {
        //connection_disable_in(uc);
    }
    
    return err;
}

int send_response_buffer(request_t* r) {
    connection_t* c= r->c;
    buffer_t* b = &r->sb;
    int err = buffer_send(b, c->fd);
{'fraction_non_alphanumeric': 0.11174648558494163, 'fraction_numerical': 0.004368199507584783, 'mean_word_length': 3.9341692789968654, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 97, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1012721', 'n_tokens_mistral': 4491, 'n_tokens_neox': 4304, 'n_words': 898}