Browse Source

Add refcount to http headers

personal/stbuehler/wip
Stefan Bühler 14 years ago
parent
commit
de6996268f
  1. 2
      src/connection.c
  2. 29
      src/http_headers.c
  3. 8
      src/http_headers.h
  4. 4
      src/request.c
  5. 4
      src/response.c

2
src/connection.c

@ -12,7 +12,7 @@ void internal_error(connection *con) {
CON_ERROR(con, "%s", "Couldn't send '500 Internal Error': headers already sent");
connection_set_state(con, CON_STATE_ERROR);
} else {
http_headers_reset(con->response.headers);
con->response.headers = http_headers_try_reset(con->response.headers);
con->response.http_status = 500;
con->content_handler = NULL;
connection_set_state(con, CON_STATE_WRITE_RESPONSE);

29
src/http_headers.c

@ -25,22 +25,47 @@ static void _header_queue_free(gpointer data, gpointer userdata) {
http_headers* http_headers_new() {
http_headers* headers = g_slice_new0(http_headers);
headers->refcount = 1;
g_queue_init(&headers->entries);
return headers;
}
void http_headers_reset(http_headers* headers) {
static void http_headers_reset(http_headers* headers) {
g_queue_foreach(&headers->entries, _header_queue_free, NULL);
g_queue_clear(&headers->entries);
}
void http_headers_free(http_headers* headers) {
static void http_headers_free(http_headers* headers) {
if (!headers) return;
g_queue_foreach(&headers->entries, _header_queue_free, NULL);
g_queue_clear(&headers->entries);
g_slice_free(http_headers, headers);
}
void http_headers_acquire(http_headers* headers) {
assert(g_atomic_int_get(&headers->refcount) > 0);
g_atomic_int_inc(&headers->refcount);
}
void http_headers_release(http_headers* headers) {
if (!headers) return;
assert(g_atomic_int_get(&headers->refcount) > 0);
if (g_atomic_int_dec_and_test(&headers->refcount)) {
http_headers_free(headers);
}
}
http_headers* http_headers_try_reset(http_headers* headers) {
assert(g_atomic_int_get(&headers->refcount) > 0);
if (g_atomic_int_dec_and_test(&headers->refcount)) {
http_headers_reset(headers);
headers->refcount = 1;
return headers;
} else {
return http_headers_new();
}
}
/** just insert normal header, allow duplicates */
void http_header_insert(http_headers *headers, const gchar *key, size_t keylen, const gchar *val, size_t valuelen) {
http_header *h = _http_header_new(key, keylen, val, valuelen);

8
src/http_headers.h

@ -21,14 +21,18 @@ struct http_header {
};
struct http_headers {
gint refcount;
GQueue entries;
};
/* strings alweays get copied, so you should free key and value yourself */
LI_API http_headers* http_headers_new();
LI_API void http_headers_reset(http_headers* headers);
LI_API void http_headers_free(http_headers* headers);
LI_API void http_headers_acquire(http_headers* headers);
LI_API void http_headers_release(http_headers* headers);
/* releases the old one; if the refcount drops to zero, reuse the memory; otherwise alloc a new one */
LI_API http_headers* http_headers_try_reset(http_headers* headers);
/** If header does not exist, just insert normal header. If it exists, append (", %s", value) */
LI_API void http_header_append(http_headers *headers, const gchar *key, size_t keylen, const gchar *value, size_t valuelen);

4
src/request.c

@ -34,7 +34,7 @@ void request_reset(request *req) {
g_string_truncate(req->uri.query, 0);
g_string_truncate(req->uri.host, 0);
http_headers_reset(req->headers);
req->headers = http_headers_try_reset(req->headers);
req->content_length = -1;
@ -53,7 +53,7 @@ void request_clear(request *req) {
g_string_free(req->uri.query, TRUE);
g_string_free(req->uri.host, TRUE);
http_headers_free(req->headers);
http_headers_release(req->headers);
req->content_length = -1;

4
src/response.c

@ -10,13 +10,13 @@ void response_init(response *resp) {
}
void response_reset(response *resp) {
http_headers_reset(resp->headers);
resp->headers = http_headers_try_reset(resp->headers);
resp->http_status = 0;
resp->transfer_encoding = HTTP_TRANSFER_ENCODING_IDENTITY;
}
void response_clear(response *resp) {
http_headers_free(resp->headers);
http_headers_release(resp->headers);
resp->http_status = 0;
resp->transfer_encoding = HTTP_TRANSFER_ENCODING_IDENTITY;
}

Loading…
Cancel
Save