mirror of
https://github.com/curl/curl.git
synced 2026-07-26 14:57:17 +03:00
lib: transfer origin and proxy handling
Add `data->state.origin` as the origin the transfer is sending the current request to/gets the response from. Use it for request specific properties like authentication, hsts and cookie handling, etc. Unless talking to a forwarding HTTP proxy (e.g. not tunneling), `data->state.origin` and `conn->origin` are the same. With a forwarding HTTP proxy in play, `conn->origin` is set to `conn->http_proxy.peer` and `conn->bits.origin_is_proxy` (a new bit) is set. Remove the connection bits, now replaced with: * `conn->bits.socksproxy` -> `conn->socks_proy.peer` * `conn->bits.httpproxy` -> `conn->http_proy.peer` * `conn->bits.proxy` -> `(conn->socks_proy.peer || conn->http_proy.peer`) * `conn->bits.tunnel_proxy` -> (`conn->http_proy.peer && !conn->bits.origin_is_proxy`) * `(conn->bits.httpproxy && !conn->bits.tunnel_proxy)` -> `conn->bits.origin_is_proxy` Rename `noproxy.[ch]` to `proxy.[ch]`. Move the connection proxy setup code from `url.c` to `proxy.c`. Remove `data->info.conn_remote_port` as no one uses it. Add test_40_02b for a SOCKS connection to a forwarding HTTPS proxy. Update internal documentation about peers and creds. Closes #21967
This commit is contained in:
parent
c951368579
commit
73daec6620
30 changed files with 1083 additions and 1014 deletions
54
lib/http2.c
54
lib/http2.c
|
|
@ -1403,7 +1403,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
|||
struct Curl_cfilter *cf = userp;
|
||||
struct cf_h2_ctx *ctx = cf->ctx;
|
||||
struct h2_stream_ctx *stream;
|
||||
struct Curl_easy *data_s;
|
||||
struct Curl_easy *data;
|
||||
int32_t stream_id = frame->hd.stream_id;
|
||||
CURLcode result;
|
||||
(void)flags;
|
||||
|
|
@ -1411,15 +1411,15 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
|||
DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
|
||||
|
||||
/* get the stream from the hash based on Stream ID */
|
||||
data_s = nghttp2_session_get_stream_user_data(session, stream_id);
|
||||
if(!GOOD_EASY_HANDLE(data_s))
|
||||
data = nghttp2_session_get_stream_user_data(session, stream_id);
|
||||
if(!GOOD_EASY_HANDLE(data))
|
||||
/* Receiving a Stream ID not in the hash should not happen, this is an
|
||||
internal error more than anything else! */
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
|
||||
stream = H2_STREAM_CTX(ctx, data_s);
|
||||
stream = H2_STREAM_CTX(ctx, data);
|
||||
if(!stream) {
|
||||
failf(data_s, "Internal NULL stream");
|
||||
failf(data, "Internal NULL stream");
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
|
|
@ -1432,14 +1432,14 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
|||
!strncmp(HTTP_PSEUDO_AUTHORITY, (const char *)name, namelen)) {
|
||||
/* pseudo headers are lower case */
|
||||
int rc = 0;
|
||||
char *check = curl_maprintf("%s:%d", cf->conn->origin->hostname,
|
||||
cf->conn->origin->port);
|
||||
char *check = curl_maprintf("%s:%d", data->state.origin->hostname,
|
||||
data->state.origin->port);
|
||||
if(!check)
|
||||
/* no memory */
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
if(!curl_strequal(check, (const char *)value) &&
|
||||
((cf->conn->origin->port != cf->conn->given->defport) ||
|
||||
!curl_strequal(cf->conn->origin->hostname, (const char *)value))) {
|
||||
((data->state.origin->port != cf->conn->given->defport) ||
|
||||
!curl_strequal(data->state.origin->hostname, (const char *)value))) {
|
||||
/* This is push is not for the same authority that was asked for in
|
||||
* the URL. RFC 7540 section 8.2 says: "A client MUST treat a
|
||||
* PUSH_PROMISE for which the server is not authoritative as a stream
|
||||
|
|
@ -1467,7 +1467,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
|||
char **headp;
|
||||
if(stream->push_headers_alloc > 1000) {
|
||||
/* this is beyond crazy many headers, bail out */
|
||||
failf(data_s, "Too many PUSH_PROMISE headers");
|
||||
failf(data, "Too many PUSH_PROMISE headers");
|
||||
free_push_headers(stream);
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
|
|
@ -1491,13 +1491,13 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
|||
|
||||
if(stream->bodystarted) {
|
||||
/* This is a trailer */
|
||||
CURL_TRC_CF(data_s, cf, "[%d] trailer: %.*s: %.*s",
|
||||
CURL_TRC_CF(data, cf, "[%d] trailer: %.*s: %.*s",
|
||||
stream->id, (int)namelen, name, (int)valuelen, value);
|
||||
result = Curl_dynhds_add(&stream->resp_trailers,
|
||||
(const char *)name, namelen,
|
||||
(const char *)value, valuelen);
|
||||
if(result) {
|
||||
cf_h2_header_error(cf, data_s, stream, result);
|
||||
cf_h2_header_error(cf, data, stream, result);
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
|
|
@ -1512,14 +1512,14 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
|||
result = Curl_http_decode_status(&stream->status_code,
|
||||
(const char *)value, valuelen);
|
||||
if(result) {
|
||||
cf_h2_header_error(cf, data_s, stream, result);
|
||||
cf_h2_header_error(cf, data, stream, result);
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
hlen = curl_msnprintf(buffer, sizeof(buffer), HTTP_PSEUDO_STATUS ":%d\r",
|
||||
stream->status_code);
|
||||
result = Curl_headers_push(data_s, buffer, hlen, CURLH_PSEUDO);
|
||||
result = Curl_headers_push(data, buffer, hlen, CURLH_PSEUDO);
|
||||
if(result) {
|
||||
cf_h2_header_error(cf, data_s, stream, result);
|
||||
cf_h2_header_error(cf, data, stream, result);
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
curlx_dyn_reset(&ctx->scratch);
|
||||
|
|
@ -1529,17 +1529,17 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
|||
if(!result)
|
||||
result = curlx_dyn_addn(&ctx->scratch, STRCONST(" \r\n"));
|
||||
if(!result)
|
||||
h2_xfer_write_resp_hd(cf, data_s, stream, curlx_dyn_ptr(&ctx->scratch),
|
||||
h2_xfer_write_resp_hd(cf, data, stream, curlx_dyn_ptr(&ctx->scratch),
|
||||
curlx_dyn_len(&ctx->scratch), FALSE);
|
||||
if(result) {
|
||||
cf_h2_header_error(cf, data_s, stream, result);
|
||||
cf_h2_header_error(cf, data, stream, result);
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
/* if we receive data for another handle, wake that up */
|
||||
if(CF_DATA_CURRENT(cf) != data_s)
|
||||
Curl_multi_mark_dirty(data_s);
|
||||
if(CF_DATA_CURRENT(cf) != data)
|
||||
Curl_multi_mark_dirty(data);
|
||||
|
||||
CURL_TRC_CF(data_s, cf, "[%d] status: HTTP/2 %03d",
|
||||
CURL_TRC_CF(data, cf, "[%d] status: HTTP/2 %03d",
|
||||
stream->id, stream->status_code);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1556,17 +1556,17 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
|
|||
if(!result)
|
||||
result = curlx_dyn_addn(&ctx->scratch, STRCONST("\r\n"));
|
||||
if(!result)
|
||||
h2_xfer_write_resp_hd(cf, data_s, stream, curlx_dyn_ptr(&ctx->scratch),
|
||||
h2_xfer_write_resp_hd(cf, data, stream, curlx_dyn_ptr(&ctx->scratch),
|
||||
curlx_dyn_len(&ctx->scratch), FALSE);
|
||||
if(result) {
|
||||
cf_h2_header_error(cf, data_s, stream, result);
|
||||
cf_h2_header_error(cf, data, stream, result);
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
/* if we receive data for another handle, wake that up */
|
||||
if(CF_DATA_CURRENT(cf) != data_s)
|
||||
Curl_multi_mark_dirty(data_s);
|
||||
if(CF_DATA_CURRENT(cf) != data)
|
||||
Curl_multi_mark_dirty(data);
|
||||
|
||||
CURL_TRC_CF(data_s, cf, "[%d] header: %.*s: %.*s",
|
||||
CURL_TRC_CF(data, cf, "[%d] header: %.*s: %.*s",
|
||||
stream->id, (int)namelen, name, (int)valuelen, value);
|
||||
|
||||
return 0; /* 0 is successful */
|
||||
|
|
@ -2840,9 +2840,7 @@ bool Curl_http2_may_switch(struct Curl_easy *data)
|
|||
(data->state.http_neg.wanted & CURL_HTTP_V2x) &&
|
||||
data->state.http_neg.h2_prior_knowledge) {
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
if(data->conn->bits.httpproxy && !data->conn->bits.tunnel_proxy) {
|
||||
/* We do not support HTTP/2 proxies yet. Also it is debatable
|
||||
whether or not this setting should apply to HTTP/2 proxies. */
|
||||
if(data->conn->bits.origin_is_proxy) {
|
||||
infof(data, "Ignoring HTTP/2 prior knowledge due to proxy");
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue