// обработка входящих пакетов void http_parsing(unsigned evdata_tcp_soc_n) { if(evdata_tcp_soc_n != http.tcp_session) return; //25.04.2013 //http.timeout = sys_clock() + HTTP_TIMEOUT; switch(http.state) { case HTTP_IDLE: case HTTP_COMPLETE: http.state = HTTP_RCV_HEADERS; req_len = 0; hdr_end = 0; http.post_content_length = 0; http.more_data = 0; // нет break, проваливаемся case HTTP_RCV_HEADERS: tcp_rx_body_pointer = 0; get_from_tcp(); // определить принят ли конец заголовков hdr_end = util_scan_caseless(req, "\r\n\r\n", req + req_len, 1); if(!hdr_end) { if(req_len == sizeof req) { http_responce_err(500); // буфер заполнен, конец не найден, слишком длинные заголовки } return; } else { int code = http_parse_headers(); switch(code) { case 290: // GET http.state = HTTP_SEND_HEADERS; http_start_get(); break; case 291: // POST http.state = HTTP_RCV_POST_DATA; drop_headers(); get_from_tcp(); // дочитать остаток из пакета, если он не влезал ранее process_post_data(); break; case 297: // OPTIONS http_responce_options(); break; default: // ошибка http_responce_err(code); break; } } break; case HTTP_RCV_POST_DATA: tcp_rx_body_pointer = 0; get_from_tcp(); process_post_data(); break; } }
static void http_read_cb(evutil_socket_t fd, short events, void *arg) { int ret = 0; struct http_connection *hc = arg; if (events & EV_TIMEOUT) { printf("timeout on fd %d, hc %p\n", fd, hc); goto failed; } if (events & EV_READ) { ret = evbuffer_read(hc->evbin, fd, 4096); if (ret == -1 || ret == 0) { goto failed; } if (hc->connection_status == HTTP_CONNECTION_STATUS_READ_HEADER) { if (evbuffer_find(hc->evbin, (const unsigned char *)"\r\n\r\n", 4) == NULL && evbuffer_get_length(hc->evbin) < 4096) { // wait to read more data return; } else { //dbprintf("evbuffer_get_length: %d\n", evbuffer_get_length(hc->evbin)); } ret = http_parse_first_line(hc, hc->evbin); if (ret) { goto failed; } ret = http_parse_headers(hc, hc->evbin); if (ret) { goto failed; } /* set no-timeout read */ event_del(hc->ev_read); event_add(hc->ev_read, NULL); hc->connection_status = HTTP_CONNECTION_STATUS_READ_BODY; } else if (hc->connection_status == HTTP_CONNECTION_STATUS_READ_BODY) { } /* dispatch to handler */ ret = http_dispatch_uri_handler_cb(hc); if (ret) { goto failed; } } return; failed: http_connection_free(hc); }
/** * @return number of octets used by this protocol, or zero upon error */ size_t http_parse(char *buf, size_t len, parse_frame *f, const parse_status *st, http *h) { size_t olen = len; const char *start = buf, *end = buf + len; if (test_resphead(buf, len, st)) { http_resp *r = &h->data.resp; h->type = HTTP_Type_RESP; /* TODO: break out to separate function a la do_parse_req() */ /* something like "HTTP/1.1 301 Moved Permanently" */ r->ver.start = buf; r->ver.len = memcspn(r->ver.start, len, " ", 1); r->code.start = r->ver.start + r->ver.len + strspn(r->ver.start + r->ver.len, " "); r->code.len = strcspn(r->code.start, " "); r->desc.start = r->code.start + r->code.len + strspn(r->code.start + r->code.len, " "); r->desc.len = strcspn(r->desc.start, "\r\n"); buf = r->desc.start + r->desc.len + strspn(r->desc.start + r->desc.len, "\r\n"); buf += http_parse_headers(buf, len - (buf - start), &r->headers); r->contents.start = buf; r->contents.len = len-(buf-start); } else if (do_test_http_header(buf, len)) { /* something like "GET / HTTP/1.1" */ size_t consumed; h->type = HTTP_Type_REQ; consumed = do_parse_req(buf, len, &h->data.req); if (consumed != 0) { buf += consumed, len -= consumed; consumed = http_parse_headers(buf, len, &h->data.req.headers); buf += consumed, len -= consumed; h->data.req.contents.start = buf; h->data.req.contents.len = len; do_req_rep(&h->data.req, st); } } else { h->type = HTTP_Type_DATA; buf += len; } f->pass = h; printf("%s -> %u\n", __func__, (unsigned)(buf-start)); return olen; }
static void test(void) { unsigned i; for (i = 0; i < sizeof TestCase / sizeof TestCase[0]; i++) { http_headers h; size_t len, bytes; len = T->len ? T->len : strlen(T->txt); printf("#%2u: ", i); dump_chars(T->txt, len, stdout); fflush(stdout); memset(&h, 0, sizeof h); bytes = http_parse_headers(T->txt, len, &h); printf(" len=%u parsed=%u\n", (unsigned)len, (unsigned)bytes); (void)http_dump_headers(&h, 0, stdout); assert(bytes <= len); T++; } }
void http_handle_EOF(connection_t *cptr) { int i, l; char *buf; mowgli_node_t *n, *tn; http_client_t *container; if (!(container = cptr->userdata)) { slog(LG_INFO, "eof() couldn't find http client"); return; } l = recvq_length(cptr); buf = smalloc(l); recvq_get(cptr, buf, l); http_parse_headers(container, buf); container->callback(container, container->userdata); }