*pnext = tail;
}
-bool Curl_conn_cf_discard_sub(struct Curl_cfilter *cf,
- struct Curl_cfilter *discard,
- struct Curl_easy *data,
- bool destroy_always)
+bool Curl_conn_cf_discard(struct Curl_cfilter **pcf,
+ struct Curl_easy *data)
{
- struct Curl_cfilter **pprev = &cf->next;
+ struct Curl_cfilter *cf = pcf ? *pcf : NULL;
bool found = FALSE;
-
- /* remove from sub-chain and destroy */
- DEBUGASSERT(cf);
- while(*pprev) {
- if(*pprev == cf) {
- *pprev = discard->next;
- discard->next = NULL;
- found = TRUE;
- break;
+ if(cf) {
+ if(cf->conn) {
+ /* unlink if present in connection filter chain */
+ struct Curl_cfilter **pprev = &cf->conn->cfilter[cf->sockindex];
+ while(*pprev) {
+ if(*pprev == *pcf) {
+ *pprev = (*pcf)->next;
+ cf->next = NULL;
+ found = TRUE;
+ break;
+ }
+ pprev = &((*pprev)->next);
+ }
}
- pprev = &((*pprev)->next);
- }
- if(found || destroy_always) {
- discard->next = NULL;
- discard->cft->destroy(discard, data);
- free(discard);
+ Curl_conn_cf_discard_chain(pcf, data);
}
return found;
}
struct Curl_cfilter *cf_new);
/**
- * Discard, e.g. remove and destroy `discard` iff
- * it still is in the filter chain below `cf`. If `discard`
- * is no longer found beneath `cf` return FALSE.
- * if `destroy_always` is TRUE, will call `discard`s destroy
- * function and free it even if not found in the subchain.
- */
-bool Curl_conn_cf_discard_sub(struct Curl_cfilter *cf,
- struct Curl_cfilter *discard,
- struct Curl_easy *data,
- bool destroy_always);
+ * Extract filter `*pcf` from its connection filter chain.
+ * Destroy `*pcf`, even if it was not part of the chain and NULL it.
+ * Returns TRUE of cf has been part of chain.
+ */
+bool Curl_conn_cf_discard(struct Curl_cfilter **pcf,
+ struct Curl_easy *data);
/**
* Discard all cfilters starting with `*pcf` and clearing it afterwards.
}
struct cf_proxy_ctx {
- /* the protocol specific sub-filter we install during connect */
- struct Curl_cfilter *cf_protocol;
int httpversion; /* HTTP version used to CONNECT */
+ BIT(sub_filter_installed);
};
CURLcode Curl_http_proxy_create_CONNECT(struct httpreq **preq,
return result;
*done = FALSE;
- if(!ctx->cf_protocol) {
- struct Curl_cfilter *cf_protocol = NULL;
+ if(!ctx->sub_filter_installed) {
int httpversion = 0;
const char *alpn = Curl_conn_cf_get_alpn_negotiated(cf->next, data);
result = Curl_cf_h1_proxy_insert_after(cf, data);
if(result)
goto out;
- cf_protocol = cf->next;
httpversion = 10;
}
else if(!alpn || !strcmp(alpn, "http/1.1")) {
result = Curl_cf_h1_proxy_insert_after(cf, data);
if(result)
goto out;
- cf_protocol = cf->next;
/* Assume that without an ALPN, we are talking to an ancient one */
httpversion = 11;
}
result = Curl_cf_h2_proxy_insert_after(cf, data);
if(result)
goto out;
- cf_protocol = cf->next;
httpversion = 20;
}
#endif
goto out;
}
- ctx->cf_protocol = cf_protocol;
+ ctx->sub_filter_installed = TRUE;
ctx->httpversion = httpversion;
/* after we installed the filter "below" us, we call connect
* on out sub-chain again.
/* subchain connected and we had already installed the protocol filter.
* This means the protocol tunnel is established, we are done.
*/
- DEBUGASSERT(ctx->cf_protocol);
+ DEBUGASSERT(ctx->sub_filter_installed);
result = CURLE_OK;
}
static void http_proxy_cf_close(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
- struct cf_proxy_ctx *ctx = cf->ctx;
-
CURL_TRC_CF(data, cf, "close");
cf->connected = FALSE;
- if(ctx->cf_protocol) {
- struct Curl_cfilter *f;
- /* if someone already removed it, we assume he also
- * took care of destroying it. */
- for(f = cf->next; f; f = f->next) {
- if(f == ctx->cf_protocol) {
- /* still in our sub-chain */
- Curl_conn_cf_discard_sub(cf, ctx->cf_protocol, data, FALSE);
- break;
- }
- }
- ctx->cf_protocol = NULL;
- }
if(cf->next)
cf->next->cft->do_close(cf->next, data);
}
const struct Curl_addrinfo *ai)
{
struct cf_ngtcp2_ctx *ctx = NULL;
- struct Curl_cfilter *cf = NULL, *udp_cf = NULL;
+ struct Curl_cfilter *cf = NULL;
CURLcode result;
(void)data;
result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
if(result)
goto out;
+ cf->conn = conn;
- result = Curl_cf_udp_create(&udp_cf, data, conn, ai, TRNSPRT_QUIC);
+ result = Curl_cf_udp_create(&cf->next, data, conn, ai, TRNSPRT_QUIC);
if(result)
goto out;
-
- cf->conn = conn;
- udp_cf->conn = cf->conn;
- udp_cf->sockindex = cf->sockindex;
- cf->next = udp_cf;
+ cf->next->conn = cf->conn;
+ cf->next->sockindex = cf->sockindex;
out:
*pcf = (!result) ? cf : NULL;
if(result) {
- if(udp_cf)
- Curl_conn_cf_discard_sub(cf, udp_cf, data, TRUE);
- Curl_safefree(cf);
- cf_ngtcp2_ctx_free(ctx);
+ if(cf)
+ Curl_conn_cf_discard_chain(&cf, data);
+ else if(ctx)
+ cf_ngtcp2_ctx_free(ctx);
}
return result;
}
const struct Curl_addrinfo *ai)
{
struct cf_osslq_ctx *ctx = NULL;
- struct Curl_cfilter *cf = NULL, *udp_cf = NULL;
+ struct Curl_cfilter *cf = NULL;
CURLcode result;
(void)data;
result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
if(result)
goto out;
+ cf->conn = conn;
- result = Curl_cf_udp_create(&udp_cf, data, conn, ai, TRNSPRT_QUIC);
+ result = Curl_cf_udp_create(&cf->next, data, conn, ai, TRNSPRT_QUIC);
if(result)
goto out;
- cf->conn = conn;
- udp_cf->conn = cf->conn;
- udp_cf->sockindex = cf->sockindex;
- cf->next = udp_cf;
+ cf->next->conn = cf->conn;
+ cf->next->sockindex = cf->sockindex;
out:
*pcf = (!result) ? cf : NULL;
if(result) {
- if(udp_cf)
- Curl_conn_cf_discard_sub(cf, udp_cf, data, TRUE);
- Curl_safefree(cf);
- cf_osslq_ctx_free(ctx);
+ if(cf)
+ Curl_conn_cf_discard_chain(&cf, data);
+ else if(ctx)
+ cf_osslq_ctx_free(ctx);
}
return result;
}
const struct Curl_addrinfo *ai)
{
struct cf_quiche_ctx *ctx = NULL;
- struct Curl_cfilter *cf = NULL, *udp_cf = NULL;
+ struct Curl_cfilter *cf = NULL;
CURLcode result;
(void)data;
result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
if(result)
goto out;
+ cf->conn = conn;
- result = Curl_cf_udp_create(&udp_cf, data, conn, ai, TRNSPRT_QUIC);
+ result = Curl_cf_udp_create(&cf->next, data, conn, ai, TRNSPRT_QUIC);
if(result)
goto out;
-
- udp_cf->conn = cf->conn;
- udp_cf->sockindex = cf->sockindex;
- cf->next = udp_cf;
+ cf->next->conn = cf->conn;
+ cf->next->sockindex = cf->sockindex;
out:
*pcf = (!result) ? cf : NULL;
if(result) {
- if(udp_cf)
- Curl_conn_cf_discard_sub(cf, udp_cf, data, TRUE);
- Curl_safefree(cf);
- cf_quiche_ctx_free(ctx);
+ if(cf)
+ Curl_conn_cf_discard_chain(&cf, data);
+ else if(ctx)
+ cf_quiche_ctx_free(ctx);
}
return result;
Curl_shutdown_clear(data, sockindex);
if(!result && !done) /* blocking failed? */
result = CURLE_SSL_SHUTDOWN_FAILED;
- Curl_conn_cf_discard_sub(head, cf, data, FALSE);
+ Curl_conn_cf_discard(&cf, data);
CURL_TRC_CF(data, cf, "shutdown and remove SSL, done -> %d", result);
break;
}