diff options
Diffstat (limited to 'src/http_resp.c')
-rw-r--r-- | src/http_resp.c | 303 |
1 files changed, 0 insertions, 303 deletions
diff --git a/src/http_resp.c b/src/http_resp.c deleted file mode 100644 index 23b2e58c..00000000 --- a/src/http_resp.c +++ /dev/null @@ -1,303 +0,0 @@ -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <assert.h> - -#include "log.h" -#include "http_resp.h" -#include "http_resp_parser.h" - -typedef struct { - chunkqueue *cq; - - chunk *c; /* current chunk in the chunkqueue */ - size_t offset; /* current offset in current chunk */ - - chunk *lookup_c; - size_t lookup_offset; - - int is_key; - int is_statusline; -} http_resp_tokenizer_t; - -http_resp *http_response_init(void) { - http_resp *resp = calloc(1, sizeof(*resp)); - - resp->reason = buffer_init(); - resp->headers = array_init(); - resp->status = -1; - - return resp; -} - -void http_response_reset(http_resp *resp) { - if (!resp) return; - - buffer_reset(resp->reason); - array_reset(resp->headers); - resp->status = -1; - -} - -void http_response_free(http_resp *resp) { - if (!resp) return; - - buffer_free(resp->reason); - array_free(resp->headers); - - free(resp); -} - -static int http_resp_get_next_char(http_resp_tokenizer_t *t, unsigned char *c) { - if (t->offset == t->c->mem->used - 1) { - /* end of chunk, open next chunk */ - - if (!t->c->next) return -1; - - t->c = t->c->next; - t->offset = 0; - } - - *c = t->c->mem->ptr[t->offset++]; - - t->lookup_offset = t->offset; - t->lookup_c = t->c; - -#if 0 - fprintf(stderr, "%s.%d: get: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->offset - 1); -#endif - - return 0; -} - -static int http_resp_lookup_next_char(http_resp_tokenizer_t *t, unsigned char *c) { - if (t->lookup_offset == t->lookup_c->mem->used - 1) { - /* end of chunk, open next chunk */ - - if (!t->lookup_c->next) return -1; - - t->lookup_c = t->lookup_c->next; - t->lookup_offset = 0; - } - - *c = t->lookup_c->mem->ptr[t->lookup_offset++]; -#if 0 - fprintf(stderr, "%s.%d: lookup: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->lookup_offset - 1); -#endif - - return 0; -} - -typedef enum { - PARSER_UNSET, - PARSER_OK, - PARSER_ERROR, - PARSER_EOF -} http_resp_parser_t; - -static http_resp_parser_t http_resp_tokenizer( - http_resp_tokenizer_t *t, - int *token_id, - buffer *token -) { - unsigned char c; - int tid = 0; - - /* push the token to the parser */ - - while (tid == 0 && 0 == http_resp_get_next_char(t, &c)) { - switch (c) { - case ':': - tid = TK_COLON; - - t->is_key = 0; - - break; - case ' ': - case '\t': - /* ignore WS */ - - break; - case '\r': - if (0 != http_resp_lookup_next_char(t, &c)) return -1; - - if (c == '\n') { - tid = TK_CRLF; - - t->c = t->lookup_c; - t->offset = t->lookup_offset; - - t->is_statusline = 0; - t->is_key = 1; - } else { - ERROR("CR with out LF at pos: %zu", t->offset); - return PARSER_ERROR; - } - break; - case '\n': - tid = TK_CRLF; - - t->is_statusline = 0; - t->is_key = 1; - - break; - default: - while (c >= 32 && c != 127 && c != 255) { - if (t->is_statusline) { - if (t->is_key && c == ':') { t->is_statusline = 0; break; } /* this is not a status line by a real header */ - if (c == 32) { t->is_key = 0; break; } /* the space is a splitter in the statusline */ - } else { - if (t->is_key) { - if (c == ':') break; /* the : is the splitter between key and value */ - } - } - if (0 != http_resp_lookup_next_char(t, &c)) return PARSER_EOF; - } - - if (t->c == t->lookup_c && - t->offset == t->lookup_offset + 1) { - - ERROR("invalid char (%d) at pos: %zu", c, t->offset); - return PARSER_ERROR; - } - - tid = TK_STRING; - - /* the lookup points to the first invalid char */ - t->lookup_offset--; - - /* no overlapping string */ - if (t->c == t->lookup_c) { - buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->lookup_offset - t->offset + 1); - } else { - /* first chunk */ - buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->c->mem->used - t->offset); - - /* chunks in the middle */ - for (t->c = t->c->next; t->c != t->lookup_c; t->c = t->c->next) { - buffer_append_string_buffer(token, t->c->mem); - t->offset = t->c->mem->used - 1; - } - - /* last chunk */ - buffer_append_string_len(token, t->c->mem->ptr, t->lookup_offset); - } - - t->offset = t->lookup_offset; - - break; - } - } - - if (tid) { - *token_id = tid; - - return PARSER_OK; - } - - return PARSER_EOF; -} - -parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *resp) { - http_resp_tokenizer_t t; - void *pParser = NULL; - int token_id = 0; - buffer *token = NULL; - http_resp_ctx_t context; - parse_status_t ret = PARSE_UNSET; - http_resp_parser_t parser_ret; - int last_token_id = 0; - - if(!cq->first) return PARSE_NEED_MORE; - t.cq = cq; - t.c = cq->first; - t.offset = t.c->offset; - t.is_key = 1; - t.is_statusline = 1; - - context.ok = 1; - context.errmsg = buffer_init(); - context.resp = resp; - context.unused_buffers = buffer_pool_init(); - - array_reset(resp->headers); - resp->status = 0; - - pParser = http_resp_parserAlloc( malloc ); - token = buffer_pool_get(context.unused_buffers); -#if 0 - http_resp_parserTrace(stderr, "http-response: "); -#endif - - while((PARSER_OK == (parser_ret = http_resp_tokenizer(&t, &token_id, token))) && context.ok) { - http_resp_parser(pParser, token_id, token, &context); - - token = buffer_pool_get(context.unused_buffers); - - /* CRLF CRLF ... the header end sequence */ - if (last_token_id == TK_CRLF && - token_id == TK_CRLF) break; - - last_token_id = token_id; - } - - // Tokenizer failed - if (parser_ret == PARSER_ERROR) { - ret = PARSE_ERROR; - } - - /* oops, the parser failed */ - if (context.ok == 0) { - ret = PARSE_ERROR; - - if (!buffer_is_empty(context.errmsg)) { - TRACE("parsing failed: %s", SAFE_BUF_STR(context.errmsg)); - } else { - TRACE("%s", "parsing failed ..."); - } - } - - http_resp_parser(pParser, 0, token, &context); - http_resp_parserFree(pParser, free); - - if (!buffer_is_empty(context.errmsg)) { - TRACE("parsing failed: %s", SAFE_BUF_STR(context.errmsg)); - } - if (context.ok == 0) { - /* we are missing the some tokens */ - - if (!buffer_is_empty(context.errmsg)) { - TRACE("parsing failed: %s", SAFE_BUF_STR(context.errmsg)); - } - - if (ret == PARSE_UNSET) { - ret = buffer_is_empty(context.errmsg) ? PARSE_NEED_MORE : PARSE_ERROR; - } - } else if (parser_ret == PARSER_EOF) { // didn't see CRLF CRLF, no other error till now - ret = PARSE_NEED_MORE; - } else { - chunk *c; - - for (c = cq->first; c != t.c; c = c->next) { - c->offset = c->mem->used - 1; - cq->bytes_out += c->mem->used - 1; - } - - c->offset = t.offset; - cq->bytes_out += t.offset; - - ret = PARSE_SUCCESS; - } - - buffer_pool_append(context.unused_buffers, token); - buffer_pool_free(context.unused_buffers); - buffer_free(context.errmsg); - - if (resp->status && (resp->status < 100 || resp->status > 999)) { - ERROR("invalid status code %i", resp->status); - return PARSE_ERROR; - } - - return ret; -} - |