-/* $OpenBSD: relay_http.c,v 1.80 2021/01/09 08:53:58 denis Exp $ */
+/* $OpenBSD: relay_http.c,v 1.81 2021/03/24 20:59:54 benno Exp $ */
/*
* Copyright (c) 2006 - 2016 Reyk Floeter <reyk@openbsd.org>
relay_calc_skip_steps(&rlay->rl_proto->rules);
}
+int
+relay_http_priv_init(struct rsession *con)
+{
+
+ struct http_session *hs;
+
+ if ((hs = calloc(1, sizeof(*hs))) == NULL)
+ return (-1);
+ SIMPLEQ_INIT(&hs->hs_methods);
+ DPRINTF("%s: session %d http_session %p", __func__,
+ con->se_id, hs);
+ con->se_priv = hs;
+ return (relay_httpdesc_init(&con->se_in));
+}
+
int
relay_httpdesc_init(struct ctl_relay_event *cre)
{
size_t size, linelen;
struct kv *hdr = NULL;
struct kv *upgrade = NULL, *upgrade_ws = NULL;
+ struct http_method_node *hmn;
+ struct http_session *hs;
+ enum httpmethod request_method;
getmonotime(&con->se_tv_last);
cre->timedout = 0;
DPRINTF("%s: session %d: header '%s: %s'", __func__,
con->se_id, key, value);
+ hs = con->se_priv;
+ DPRINTF("%s: session %d http_session %p", __func__,
+ con->se_id, hs);
+
/*
* Identify and handle specific HTTP request methods
*/
if (cre->line == 1 && cre->dir == RELAY_DIR_RESPONSE) {
desc->http_method = HTTP_METHOD_RESPONSE;
+ hmn = SIMPLEQ_FIRST(&hs->hs_methods);
+
+ /*
+ * There is nothing preventing the relay to send
+ * an unbalanced response. Be prepared.
+ */
+ if (hmn == NULL) {
+ request_method = HTTP_METHOD_NONE;
+ DPRINTF("%s: session %d unbalanced response",
+ __func__, con->se_id);
+ } else {
+ SIMPLEQ_REMOVE_HEAD(&hs->hs_methods, hmn_entry);
+ request_method = hmn->hmn_method;
+ DPRINTF("%s: session %d dequeing %s", __func__,
+ con->se_id,
+ relay_httpmethod_byid(request_method));
+ free(hmn);
+ }
+
/*
* Decode response path and query
*/
free(line);
goto fail;
}
+ if ((hmn = calloc(1, sizeof *hmn)) == NULL) {
+ free(line);
+ goto fail;
+ }
+ hmn->hmn_method = desc->http_method;
+ DPRINTF("%s: session %d enqueing %s", __func__,
+ con->se_id,
+ relay_httpmethod_byid(hmn->hmn_method));
+ SIMPLEQ_INSERT_TAIL(&hs->hs_methods, hmn, hmn_entry);
/*
* Decode request path and query
*/
goto abort;
}
/*
- * Need to read data from the client after the
- * HTTP header.
- * XXX What about non-standard clients not using
- * the carriage return? And some browsers seem to
- * include the line length in the content-length.
+ * HEAD responses may provide a Content-Length header,
+ * but if so it should just be ignored, since there is
+ * no actual payload in the response.
*/
- cre->toread = strtonum(value, 0, LLONG_MAX, &errstr);
- if (errstr) {
- relay_abort_http(con, 500, errstr, 0);
- goto abort;
+ if (desc->http_method != HTTP_METHOD_RESPONSE
+ || request_method != HTTP_METHOD_HEAD) {
+ /*
+ * Need to read data from the client after the
+ * HTTP header.
+ * XXX What about non-standard clients not
+ * using the carriage return? And some browsers
+ * seem to include the line length in the
+ * content-length.
+ */
+ cre->toread = strtonum(value, 0, LLONG_MAX,
+ &errstr);
+ if (errstr) {
+ relay_abort_http(con, 500, errstr, 0);
+ goto abort;
+ }
}
/*
* response with a status code of 1xx
case HTTP_METHOD_SEARCH:
case HTTP_METHOD_PATCH:
/* HTTP request payload */
- if (cre->toread > 0)
+ if (cre->toread > 0) {
bev->readcb = relay_read_httpcontent;
+ }
/* Single-pass HTTP body */
if (cre->toread < 0) {
void
relay_close_http(struct rsession *con)
{
+ struct http_session *hs = con->se_priv;
+ struct http_method_node *hmn;
+
+ DPRINTF("%s: session %d http_session %p", __func__,
+ con->se_id, hs);
+ if (hs != NULL)
+ while (!SIMPLEQ_EMPTY(&hs->hs_methods)) {
+ hmn = SIMPLEQ_FIRST(&hs->hs_methods);
+ SIMPLEQ_REMOVE_HEAD(&hs->hs_methods, hmn_entry);
+ DPRINTF("%s: session %d freeing %s", __func__,
+ con->se_id, relay_httpmethod_byid(hmn->hmn_method));
+ free(hmn);
+ }
relay_httpdesc_free(con->se_in.desc);
free(con->se_in.desc);
relay_httpdesc_free(con->se_out.desc);