static int on_body(http_parser *const parser, char const *const at, size_t const len) { HTTPConnectionRef const conn = parser->data; conn->type = HTTPBody; *conn->out = uv_buf_init((char *)at, len); http_parser_pause(parser, 1); return 0; }
static int hm_parser_message_complete_cb(http_parser* parser) { HMParser *hm_parser = (HMParser*)parser; hm_parser->state = HM_PARSER_STATE_MESSAGE_COMPLETE; hm_parser->last_id = hm_piece_none; http_parser_pause(parser, 1); return 0; }
static int on_headers_complete(http_parser *const parser) { HTTPConnectionRef const conn = parser->data; conn->type = HTTPHeadersComplete; *conn->out = uv_buf_init(NULL, 0); http_parser_pause(parser, 1); return 0; }
uint32_t http_tokenizer_execute(http_tokenizer* tokenizer, const char *data, uint32_t len) { http_parser* parser = &(tokenizer->parser); static const http_parser_settings settings = { .on_message_begin = http_tokenizer_message_begin_cb, .on_url = http_tokenizer_url_cb, .on_header_field = http_tokenizer_header_field_cb, .on_header_value = http_tokenizer_header_value_cb, .on_headers_complete = http_tokenizer_headers_complete_cb, .on_body = http_tokenizer_body_cb, .on_message_complete = http_tokenizer_message_complete_cb }; /* clear old tokens. */ tokenizer->count = 0; /* save start of data pointer for offset calculation. */ parser->data = (void *)data; if(parser->http_errno == HPE_PAUSED) { /* resume parser. */ http_parser_pause(parser, 0); } /* parse data into tokens. */ return http_parser_execute(parser, &settings, data, len); }
int on_message_complete (http_parser *parser) { EMIT_VERSION_ONCE(parser); parser_data *data = (parser_data *)parser->data; data->result = enif_make_list_cell(data->env, k_atom_done, data->result); http_parser_pause(parser, 1); return 0; }
static int on_body(http_parser *const parser, char const *const at, size_t const len) { HTTPMessageRef const msg = parser->data; assertf(0 == msg->next.len, "Chunk already waiting"); assertf(!msg->eof, "Message already complete"); msg->next.at = at; msg->next.len = len; http_parser_pause(parser, 1); return 0; }
static int on_message_complete(http_parser *const parser) { HTTPConnectionRef const conn = parser->data; assert(HTTPMessageIncomplete & conn->flags); conn->type = HTTPMessageEnd; *conn->out = uv_buf_init(NULL, 0); conn->flags &= ~HTTPMessageIncomplete; http_parser_pause(parser, 1); return 0; }
int Pillow::HttpResponseParser::parser_on_message_complete(http_parser *parser) { Pillow::HttpResponseParser* self = reinterpret_cast<Pillow::HttpResponseParser*>(parser->data); self->messageComplete(); // Pause the parser to avoid parsing the next message (if there is another one in the buffer). http_parser_pause(parser, 1); return 0; }
int HTTPConnectionPeek(HTTPConnectionRef const conn, HTTPEvent *const type, uv_buf_t *const buf) { if(!conn) return UV_EINVAL; if(!type) return UV_EINVAL; if(!buf) return UV_EINVAL; size_t len; int rc; if(HTTPStreamEOF & conn->flags) return UV_EOF; // Repeat previous errors. rc = HTTP_PARSER_ERRNO(conn->parser); if(HPE_OK != rc && HPE_PAUSED != rc) return UV_UNKNOWN; while(HTTPNothing == conn->type) { if(!conn->raw->len) { // It might seem counterintuitive to free the buffer // just before we could reuse it, but the one time we // don't need it is while blocking. We could free it // after a timeout to give us a chance to reuse it, // but even the two second timeout Apache uses causes // a lot of problems... FREE(&conn->buf); *conn->raw = uv_buf_init(NULL, 0); *conn->out = uv_buf_init(NULL, 0); rc = async_read((uv_stream_t *)conn->stream, conn->raw); if(UV_EOF == rc) conn->flags |= HTTPStreamEOF; if(rc < 0) return rc; conn->buf = conn->raw->base; } http_parser_pause(conn->parser, 0); len = http_parser_execute(conn->parser, &settings, conn->raw->base, conn->raw->len); rc = HTTP_PARSER_ERRNO(conn->parser); // HACK: http_parser returns 1 when the input length is 0 (EOF). if(len > conn->raw->len) len = conn->raw->len; conn->raw->base += len; conn->raw->len -= len; if(HPE_OK != rc && HPE_PAUSED != rc) { // TODO: We should convert HPE_* and return them // instead of logging and returning UV_UNKNOWN. fprintf(stderr, "HTTP parse error %s (%d)\n", http_errno_name(rc), HTTP_PARSER_ERRNO_LINE(conn->parser)); // fprintf(stderr, "%s (%lu)\n", strndup(conn->raw->base, conn->raw->len), conn->raw->len); return UV_UNKNOWN; } } assertf(HTTPNothing != conn->type, "HTTPConnectionPeek must return an event"); *type = conn->type; *buf = *conn->out; return 0; }
static int hm_parser_headers_complete_cb(http_parser* parser) { HMParser *hm_parser = (HMParser*)parser; hm_parser->state = HM_PARSER_STATE_HEADERS_COMPLETE; hm_parser->last_id = hm_piece_none; /* mark end of headers. */ if(hm_parser->headers_start != HM_PIECE_INVALID) { hm_parser->headers_end = hm_array_count(hm_parser->pieces); } if(parser->type == HTTP_RESPONSE) { http_parser_pause(parser, 1); } return 0; }
static int http_tokenizer_grow(http_tokenizer* tokenizer) { uint32_t len = tokenizer->len + GROW_TOKENS; http_token *tokens; if(len > HTTP_TOKENIZER_MAX_TOKENS) return -1; tokens = (http_token *)realloc(tokenizer->tokens, sizeof(http_token) * len); if(tokens == NULL) return -1; tokenizer->tokens = tokens; tokenizer->len = len; if((len + GROW_TOKENS) > HTTP_TOKENIZER_MAX_TOKENS) { /* can't hold any more tokens, pause parsing. */ http_parser_pause(&(tokenizer->parser), 1); } return 0; }
static int on_header_field(http_parser *const parser, char const *const at, size_t const len) { HTTPMessageRef const msg = parser->data; if(msg->headers) { if(msg->next.at) { HeadersAppendFieldChunk(msg->headers, msg->next.at, msg->next.len); msg->next.at = NULL; msg->next.len = 0; } HeadersAppendFieldChunk(msg->headers, at, len); } else { assertf(0 == msg->next.len, "Chunk already waiting"); msg->next.at = at; msg->next.len = len; http_parser_pause(parser, 1); } return 0; }
static int on_message_complete (http_parser * parser) { lwp_ws_httpclient ctx = (lwp_ws_httpclient) parser->data; if (!ctx->client.multipart) lwp_ws_req_call_hook (ctx->request); ctx->parsing_headers = lw_true; /* Since we're now transitioning back to parsing headers, our sink method * needs to start reading lines again (if it's currently reading the * body). Pausing the parser returns control to the sink method. */ http_parser_pause (parser, 1); return 0; }
static int hm_parser_resume_parse(HMParser *hm_parser, char *data, size_t data_len) { http_parser* parser = &(hm_parser->parser); static const http_parser_settings settings = { .on_message_begin = hm_parser_message_begin_cb, .on_url = hm_parser_url_cb, .on_status_complete = hm_parser_status_complete_cb, .on_header_field = hm_parser_header_field_cb, .on_header_value = hm_parser_header_value_cb, .on_headers_complete = hm_parser_headers_complete_cb, .on_body = hm_parser_body_cb, .on_message_complete = hm_parser_message_complete_cb }; /* resume http parser. */ size_t nparsed = http_parser_execute(parser, &settings, data, data_len); if(nparsed > 0) { hm_parser->parsed_off += nparsed; if(hm_parser->state == HM_PARSER_STATE_HEADERS) { hm_parser->headers_end = hm_array_count(hm_parser->pieces); } if(hm_parser->state == HM_PARSER_STATE_BODY) { hm_parser->body_end = hm_array_count(hm_parser->pieces); } } /* check for error. */ if(parser->http_errno != HPE_OK) { /* check if parser was paused. */ if(parser->http_errno == HPE_PAUSED) { /* resume parser. */ http_parser_pause(parser, 0); /* check if buffer is also empty. */ if(hm_parser->parsed_off == hm_parser->buf_len) { hm_parser->state |= HM_PARSER_STATE_NEEDS_INPUT; } } else { /* return -1 to indicate a parser error. */ hm_parser->state |= HM_PARSER_STATE_ERROR; } return -1; } return nparsed; }
static int on_http_req_message_complete(http_parser *parser) { struct connection_context *conn = parser->data; if (conn->verbose) printf("%s: request type: %s\n", conn->label, http_method_str(parser->method)); conn->ishead = (HTTP_HEAD == parser->method); /* * Exit the request parser so the response can be processed. This * protects the request state needed by the response parser from * being overwritten early. */ http_parser_pause(parser, 1); return (0); }
static int on_http_resp_message_complete(http_parser *parser) { struct connection_context *conn = parser->data; if (conn->verbose > 1) printf("%s: response complete\n", conn->label); if (conn->extract_body) { if (conn->inflate) { inflateEnd(&conn->zstrm); } close(conn->fd); } /* * Exit the response parser so the next request can be processed. */ http_parser_pause(parser, 1); return (0); }
VALUE rb_parser_resume(VALUE self) { http_parser *parser = rb_http_parser_handle(self); http_parser_pause(parser, 0); return Qtrue; }
static int http_tokenizer_message_complete_cb(http_parser* parser) { if(http_push_token(parser, HTTP_TOKEN_MESSAGE_COMPLETE) < 0) return -1; http_parser_pause(parser, 1); return 0; }
/* * The passive http extraction code works by alternately parsing the * passively reconstructed request and response streams. The same callback * (below) is used to drive the parsing of each stream. Parsing begins with * the request stream, and once a complete request has been parsed, the * parser and read watcher for the request stream are paused and the parser * and read watcher for the response stream are activated. Once an entire * response is parsed, the parser and read watcher for the response stream * are paused, and the parser and read watcher for the request stream are * activated. Along the way, response bodies that match the supplied list * of content types are extracted to files. * * This is example code whose purpose is to demonstrate upper layer protocol * processing using libuinet passive sockets functionality. Little to no * attempt is made to deal with a number of ugly realities involved in * robustly parsing http streams in the wild. */ static void passive_extract_cb(struct ev_loop *loop, ev_uinet *w, int revents) { struct connection_context *conn = (struct connection_context *)w->data; struct uinet_iovec iov; struct uinet_uio uio; int max_read; int read_size; int bytes_read; int error; int flags; size_t nparsed; max_read = uinet_soreadable(w->so, 0); if (max_read <= 0) { /* the watcher should never be invoked if there is no error and there no bytes to be read */ assert(max_read != 0); /* * There are no more complete requests/responses to be had, shut everything down. */ if (conn->verbose) printf("%s: can't read, closing\n", conn->label); goto err; } else { read_size = imin(max_read, conn->buffer_size - conn->buffer_index); uio.uio_iov = &iov; iov.iov_base = &conn->buffer[conn->buffer_index]; iov.iov_len = read_size; uio.uio_iovcnt = 1; uio.uio_offset = 0; uio.uio_resid = read_size; flags = UINET_MSG_HOLE_BREAK; error = uinet_soreceive(w->so, NULL, &uio, &flags); if (0 != error) { printf("%s: read error (%d), closing\n", conn->label, error); goto err; } if (flags & UINET_MSG_HOLE_BREAK) { printf("%s: hole in data, closing connections\n", conn->label); goto err; } bytes_read = read_size - uio.uio_resid; conn->buffer_count += bytes_read; conn->bytes_read += bytes_read; do { passive_extract_parse_buffer(conn); if (HTTP_PARSER_ERRNO(conn->parser) != HPE_OK) { if (HTTP_PARSER_ERRNO(conn->parser) == HPE_PAUSED) { if (conn->verbose > 1) printf("%s: completed parsing request or response\n", conn->label); http_parser_pause(conn->peer->parser, 0); passive_extract_parse_buffer(conn->peer); if (HTTP_PARSER_ERRNO(conn->peer->parser) == HPE_OK) { if (conn->verbose > 1) printf("%s: peer needs more data\n", conn->label); /* Peer parser needs more data */ ev_uinet_stop(conn->server->loop, &conn->watcher); ev_uinet_start(conn->server->loop, &conn->peer->watcher); break; } else if (HTTP_PARSER_ERRNO(conn->peer->parser) != HPE_PAUSED) { printf("Peer parse failure %s, closing connections\n", http_errno_name(HTTP_PARSER_ERRNO(conn->peer->parser))); goto err; } else { if (conn->verbose > 1) printf("%s: peer completed parsing request or response\n", conn->label); /* * The other parser has paused, so it's time for us to continue * parsing/receiving. */ http_parser_pause(conn->parser, 0); } } else { printf("Parse failure %s, closing connections\n", http_errno_name(HTTP_PARSER_ERRNO(conn->parser))); goto err; } } } while (conn->buffer_count); } return; err: /* * Deliver EOS to each parser. If a parser is paused or otherwise * in an error state, no work will be done. The main reason for * doing this is to correctly handle the case where response parsing * requires an EOS to complete. Under such circumstances, one of * the calls below will complete the work. */ http_parser_execute(conn->parser, conn->parser_settings, NULL, 0); http_parser_execute(conn->peer->parser, conn->peer->parser_settings, NULL, 0); destroy_conn(conn->peer); destroy_conn(conn); }
static int on_message_complete(http_parser *parser) { http_parser_pause(parser, true); return 0; }
static int on_headers_complete(http_parser *const parser) { HTTPMessageRef const msg = parser->data; HeadersEnd(msg->headers); http_parser_pause(parser, 1); return 0; }
void response_parser::set_paused(bool is_paused) { int paused = is_paused ? 1 : 0; http_parser_pause(&_parser, paused); }
void Pillow::HttpResponseParser::pause() { http_parser_pause(&parser, 1); }