Пример #1
0
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;
}
Пример #2
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;
}
Пример #3
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;
}
Пример #4
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);
}
Пример #5
0
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;
}
Пример #7
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;
}
Пример #8
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;
}
Пример #9
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;
}
Пример #10
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;
}
Пример #11
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;
}
Пример #13
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;
}
Пример #14
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;
}
Пример #15
0
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);
}
Пример #16
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);
}
Пример #17
0
VALUE rb_parser_resume(VALUE self) {
    http_parser *parser = rb_http_parser_handle(self);
    http_parser_pause(parser, 0);
    return Qtrue;
}
Пример #18
0
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;
}
Пример #19
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);
}
Пример #20
0
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;
}
Пример #22
0
void response_parser::set_paused(bool is_paused) 
{
    int paused = is_paused ? 1 : 0;
    http_parser_pause(&_parser, paused);
}
Пример #23
0
void Pillow::HttpResponseParser::pause()
{
	http_parser_pause(&parser, 1);
}