Mercurial > urweb
diff src/c/request.c @ 856:86ec89baee01
cgi protocol
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Tue, 23 Jun 2009 17:59:23 -0400 |
parents | 158d980889ac |
children | 305bc0a431de |
line wrap: on
line diff
--- a/src/c/request.c Tue Jun 23 15:56:04 2009 -0400 +++ b/src/c/request.c Tue Jun 23 17:59:23 2009 -0400 @@ -17,11 +17,11 @@ #define MAX_RETRIES 5 -static int try_rollback(uw_context ctx) { +static int try_rollback(uw_context ctx, void *logger_data, uw_logger log_error) { int r = uw_rollback(ctx); if (r) { - printf("Error running SQL ROLLBACK\n"); + log_error(logger_data, "Error running SQL ROLLBACK\n"); uw_reset(ctx); uw_write(ctx, "HTTP/1.1 500 Internal Server Error\n\r"); uw_write(ctx, "Content-type: text/plain\r\n\r\n"); @@ -31,7 +31,7 @@ return r; } -uw_context uw_request_new_context() { +uw_context uw_request_new_context(void *logger_data, uw_logger log_error, uw_logger log_debug) { uw_context ctx = uw_init(); int retries_left = MAX_RETRIES; @@ -39,25 +39,25 @@ failure_kind fk = uw_begin_init(ctx); if (fk == SUCCESS) { - printf("Database connection initialized.\n"); + log_debug(logger_data, "Database connection initialized.\n"); break; } else if (fk == BOUNDED_RETRY) { if (retries_left) { - printf("Initialization error triggers bounded retry: %s\n", uw_error_message(ctx)); + log_debug(logger_data, "Initialization error triggers bounded retry: %s\n", uw_error_message(ctx)); --retries_left; } else { - printf("Fatal initialization error (out of retries): %s\n", uw_error_message(ctx)); + log_error(logger_data, "Fatal initialization error (out of retries): %s\n", uw_error_message(ctx)); uw_free(ctx); return NULL; } } else if (fk == UNLIMITED_RETRY) - printf("Initialization error triggers unlimited retry: %s\n", uw_error_message(ctx)); + log_debug(logger_data, "Initialization error triggers unlimited retry: %s\n", uw_error_message(ctx)); else if (fk == FATAL) { - printf("Fatal initialization error: %s\n", uw_error_message(ctx)); + log_error(logger_data, "Fatal initialization error: %s\n", uw_error_message(ctx)); uw_free(ctx); return NULL; } else { - printf("Unknown uw_begin_init return code!\n"); + log_error(logger_data, "Unknown uw_begin_init return code!\n"); uw_free(ctx); return NULL; } @@ -78,7 +78,7 @@ static int password[PASSSIZE]; static unsigned char private_key[KEYSIZE]; -static void init_crypto() { +static void init_crypto(void *logger_data, uw_logger log_error) { KEYGEN kg = {{HASH_ALGORITHM, HASH_ALGORITHM}}; int i; @@ -90,37 +90,37 @@ if (mhash_keygen_ext(KEYGEN_ALGORITHM, kg, private_key, sizeof(private_key), (unsigned char*)password, sizeof(password)) < 0) { - printf("Key generation failed\n"); + log_error(logger_data, "Key generation failed\n"); exit(1); } } -void uw_request_init() { +void uw_request_init(void *logger_data, uw_logger log_error, uw_logger log_debug) { uw_context ctx; failure_kind fk; uw_global_init(); - ctx = uw_request_new_context(); + ctx = uw_request_new_context(logger_data, log_error, log_debug); if (!ctx) exit(1); for (fk = uw_initialize(ctx); fk == UNLIMITED_RETRY; fk = uw_initialize(ctx)) { - printf("Unlimited retry during init: %s\n", uw_error_message(ctx)); + log_debug(logger_data, "Unlimited retry during init: %s\n", uw_error_message(ctx)); uw_db_rollback(ctx); uw_reset(ctx); } if (fk != SUCCESS) { - printf("Failed to initialize database! %s\n", uw_error_message(ctx)); + log_error(logger_data, "Failed to initialize database! %s\n", uw_error_message(ctx)); uw_db_rollback(ctx); exit(1); } uw_free(ctx); - init_crypto(); + init_crypto(logger_data, log_error); } void uw_sign(const char *in, char *out) { @@ -131,7 +131,7 @@ mhash(td, in, strlen(in)); if (mhash_hmac_deinit(td, out) < 0) - printf("Signing failed"); + fprintf(stderr, "Signing failed\n"); } typedef struct uw_rc { @@ -154,6 +154,8 @@ request_result uw_request(uw_request_context rc, uw_context ctx, char *method, char *path, char *query_string, char *body, size_t body_len, + void (*on_success)(uw_context), void (*on_failure)(uw_context), + void *logger_data, uw_logger log_error, uw_logger log_debug, int sock) { int retries_left = MAX_RETRIES; char *s; @@ -166,17 +168,17 @@ if (!strcmp(method, "POST")) { char *clen_s = uw_Basis_requestHeader(ctx, "Content-length"); if (!clen_s) { - fprintf(stderr, "No Content-length with POST\n"); + log_error(logger_data, "No Content-length with POST\n"); return FAILED; } int clen = atoi(clen_s); if (clen < 0) { - fprintf(stderr, "Negative Content-length with POST\n"); + log_error(logger_data, "Negative Content-length with POST\n"); return FAILED; } if (body_len < clen) { - fprintf(stderr, "Request doesn't contain all POST data (according to Content-Length)\n"); + log_error(logger_data, "Request doesn't contain all POST data (according to Content-Length)\n"); return FAILED; } @@ -185,7 +187,7 @@ clen_s = uw_Basis_requestHeader(ctx, "Content-type"); if (clen_s && !strncasecmp(clen_s, "multipart/form-data", 19)) { if (strncasecmp(clen_s + 19, "; boundary=", 11)) { - fprintf(stderr, "Bad multipart boundary spec"); + log_error(logger_data, "Bad multipart boundary spec"); return FAILED; } @@ -195,7 +197,7 @@ boundary_len = strlen(boundary); } } else if (strcmp(method, "GET")) { - fprintf(stderr, "Not ready for non-GET/POST command: %s\n", method); + log_error(logger_data, "Not ready for non-GET/POST command: %s\n", method); return FAILED; } @@ -204,18 +206,18 @@ char *pass = uw_Basis_requestHeader(ctx, "UrWeb-Pass"); if (sock < 0) { - fprintf(stderr, ".msgs requested, but not socket supplied\n"); + log_error(logger_data, ".msgs requested, but not socket supplied\n"); return FAILED; } if (id && pass) { unsigned idn = atoi(id); uw_client_connect(idn, atoi(pass), sock); - fprintf(stderr, "Processed request for messages by client %u\n\n", idn); + log_error(logger_data, "Processed request for messages by client %u\n\n", idn); return KEEP_OPEN; } else { - fprintf(stderr, "Missing fields in .msgs request: %s, %s\n\n", id, pass); + log_error(logger_data, "Missing fields in .msgs request: %s, %s\n\n", id, pass); return FAILED; } } @@ -226,7 +228,7 @@ part = strstr(part, boundary); if (!part) { - fprintf(stderr, "Missing first multipart boundary\n"); + log_error(logger_data, "Missing first multipart boundary\n"); return FAILED; } part += boundary_len; @@ -238,18 +240,18 @@ break; if (*part != '\r') { - fprintf(stderr, "No \\r after multipart boundary\n"); + log_error(logger_data, "No \\r after multipart boundary\n"); return FAILED; } ++part; if (*part != '\n') { - fprintf(stderr, "No \\n after multipart boundary\n"); + log_error(logger_data, "No \\n after multipart boundary\n"); return FAILED; } ++part; if (!(after_sub_headers = strstr(part, "\r\n\r\n"))) { - fprintf(stderr, "Missing end of headers after multipart boundary\n"); + log_error(logger_data, "Missing end of headers after multipart boundary\n"); return FAILED; } after_sub_headers[2] = 0; @@ -260,18 +262,18 @@ *after_header = 0; if (!(colon = strchr(header, ':'))) { - fprintf(stderr, "Missing colon in multipart sub-header\n"); + log_error(logger_data, "Missing colon in multipart sub-header\n"); return FAILED; } *colon++ = 0; if (*colon++ != ' ') { - fprintf(stderr, "No space after colon in multipart sub-header\n"); + log_error(logger_data, "No space after colon in multipart sub-header\n"); return FAILED; } if (!strcasecmp(header, "Content-Disposition")) { if (strncmp(colon, "form-data; ", 11)) { - fprintf(stderr, "Multipart data is not \"form-data\"\n"); + log_error(logger_data, "Multipart data is not \"form-data\"\n"); return FAILED; } @@ -279,12 +281,12 @@ char *data; after_colon[0] = 0; if (after_colon[1] != '"') { - fprintf(stderr, "Disposition setting is missing initial quote\n"); + log_error(logger_data, "Disposition setting is missing initial quote\n"); return FAILED; } data = after_colon+2; if (!(after_colon = strchr(data, '"'))) { - fprintf(stderr, "Disposition setting is missing final quote\n"); + log_error(logger_data, "Disposition setting is missing final quote\n"); return FAILED; } after_colon[0] = 0; @@ -304,7 +306,7 @@ part = memmem(after_sub_headers, body + body_len - after_sub_headers, boundary, boundary_len); if (!part) { - fprintf(stderr, "Missing boundary after multipart payload\n"); + log_error(logger_data, "Missing boundary after multipart payload\n"); return FAILED; } part[-2] = 0; @@ -316,11 +318,11 @@ uw_Basis_file f = {filename, type, {part_len, after_sub_headers}}; if (uw_set_file_input(ctx, name, f)) { - fprintf(stderr, "%s\n", uw_error_message(ctx)); + log_error(logger_data, "%s\n", uw_error_message(ctx)); return FAILED; } } else if (uw_set_input(ctx, name, after_sub_headers)) { - fprintf(stderr, "%s\n", uw_error_message(ctx)); + log_error(logger_data, "%s\n", uw_error_message(ctx)); return FAILED; } } @@ -341,24 +343,24 @@ if (value = strchr(name, '=')) { *value++ = 0; if (uw_set_input(ctx, name, value)) { - fprintf(stderr, "%s\n", uw_error_message(ctx)); + log_error(logger_data, "%s\n", uw_error_message(ctx)); return FAILED; } } else if (uw_set_input(ctx, name, "")) { - fprintf(stderr, "%s\n", uw_error_message(ctx)); + log_error(logger_data, "%s\n", uw_error_message(ctx)); return FAILED; } } } } - printf("Serving URI %s....\n", path); + log_debug(logger_data, "Serving URI %s....\n", path); while (1) { size_t path_len = strlen(path); - uw_write_header(ctx, "HTTP/1.1 200 OK\r\n"); + on_success(ctx); if (path_len + 1 > rc->path_copy_size) { rc->path_copy_size = path_len + 1; @@ -371,16 +373,16 @@ return SERVED; } else if (fk == BOUNDED_RETRY) { if (retries_left) { - printf("Error triggers bounded retry: %s\n", uw_error_message(ctx)); + log_debug(logger_data, "Error triggers bounded retry: %s\n", uw_error_message(ctx)); --retries_left; } else { - printf("Fatal error (out of retries): %s\n", uw_error_message(ctx)); + log_error(logger_data, "Fatal error (out of retries): %s\n", uw_error_message(ctx)); - try_rollback(ctx); + try_rollback(ctx, logger_data, log_error); uw_reset_keep_error_message(ctx); - uw_write_header(ctx, "HTTP/1.1 500 Internal Server Error\n\r"); + on_failure(ctx); uw_write_header(ctx, "Content-type: text/plain\r\n"); uw_write(ctx, "Fatal error (out of retries): "); uw_write(ctx, uw_error_message(ctx)); @@ -389,14 +391,14 @@ return FAILED; } } else if (fk == UNLIMITED_RETRY) - printf("Error triggers unlimited retry: %s\n", uw_error_message(ctx)); + log_debug(logger_data, "Error triggers unlimited retry: %s\n", uw_error_message(ctx)); else if (fk == FATAL) { - printf("Fatal error: %s\n", uw_error_message(ctx)); + log_error(logger_data, "Fatal error: %s\n", uw_error_message(ctx)); - try_rollback(ctx); + try_rollback(ctx, logger_data, log_error); uw_reset_keep_error_message(ctx); - uw_write_header(ctx, "HTTP/1.1 500 Internal Server Error\r\n"); + on_failure(ctx); uw_write_header(ctx, "Content-type: text/html\r\n"); uw_write(ctx, "<html><head><title>Fatal Error</title></head><body>"); uw_write(ctx, "Fatal error: "); @@ -405,27 +407,33 @@ return FAILED; } else { - printf("Unknown uw_handle return code!\n"); + log_error(logger_data, "Unknown uw_handle return code!\n"); - try_rollback(ctx); + try_rollback(ctx, logger_data, log_error); uw_reset_keep_request(ctx); - uw_write_header(ctx, "HTTP/1.1 500 Internal Server Error\n\r"); + on_failure(ctx); uw_write_header(ctx, "Content-type: text/plain\r\n"); uw_write(ctx, "Unknown uw_handle return code!\n"); return FAILED; } - if (try_rollback(ctx)) + if (try_rollback(ctx, logger_data, log_error)) return FAILED; uw_reset_keep_request(ctx); } } +typedef struct { + void *logger_data; + uw_logger log_error, log_debug; +} loggers; + void *client_pruner(void *data) { - uw_context ctx = uw_request_new_context(); + loggers *ls = (loggers *)data; + uw_context ctx = uw_request_new_context(ls->logger_data, ls->log_error, ls->log_debug); if (!ctx) exit(1);