curl / Mailing Lists / curl-library / Single Mail
Buy commercial curl support from WolfSSL. We help you work out your issues, debug your libcurl applications, use the API, port to new platforms, add new features and more. With a team lead by the curl founder himself.

Re: Support HTTP2 Goaway Frame callback for curl multi

From: Ray Satiro via curl-library <curl-library_at_lists.haxx.se>
Date: Fri, 5 Jan 2024 15:35:16 -0500

On 1/5/2024 11:28 AM, Cao Duc Quan via curl-library wrote:
> 1. Open a new HTTP2 connection by creating an HTTP GET to an url path.
> I created a CURLM object and added the easy handle for HTTP GET
> Request to it.
> 2. Next HTTP request will be sent in the HTTP2 connection created by
> step 1. I created a new easy handle for this request and added it to
> CURLM object created in step 1.
> 3. After a few hours or less, the connection at step 1 will be closed
> by server side (due to idle timeout or TTL). The server will send a
> GOAWAY frame to start Graceful shutdown before explicitly closing it
> after 60s so that both Client and Server could finish their in-flight
> transferring.
> 4. My library needs to detect the connection is closed and reopen a
> new one (step 1).
>
> So I have a problem at step 2:
> - If the connection created by step 1 received a GOAWAY frame, cURL
> will open a new HTTP2 to send the next HTTP request. The new HTTP2
> request will fail because there is some logic check at server side to
> ensure only connection created by step 1 is allowed. I believe this is
> odd checking but that is the logic from the server side and I could
> not change it.


If the first connection has idled approximately 2 minutes (118 seconds)
[1] then curl should close it before before processing the next transfer
on the new connection. If a GOAWAY frame is received on the first
connection before then (either bundled with the previous request or due
to a timeout in the interim) it *should* do the same thing:

* received GOAWAY, error=0, last_stream=1
* Connection 0 seems to be dead
* The cache now contains 0 members
* Curl_disconnect(conn #0, dead=1)
* Closing connection
* TLSv1.2 (IN), TLS alert, close notify (256):
* TLSv1.2 (OUT), TLS alert, close notify (256):

The connection cache logic for that is in function extract_if_dead [2].

nginx test #1:
- set `http2_max_requests 1;`
- `sudo systemctl reload nginx.service` to reload the config
- first curl_easy_perform
- first transfer reply and curl receives GOAWAY
- second curl_easy_perform
- curl opens a new connection for the second transfer
- second transfer reply

nginx test #2:
- unset `http2_max_requests 1;`
- set `http2_idle_timeout 30s;`
- `sudo systemctl reload nginx.service` to reload the config
- first curl_easy_perform
- first transfer reply and curl does not receive GOAWAY
- wait 1 minute (GOAWAY packet sent by nginx during this time according
to wireshark)
- second curl_easy_perform
- curl receives GOAWAY before initiating the second transfer
- curl opens a new connection for the second transfer
- second transfer reply

If curl is working as intended then I do not understand why your
application needs to handle GOAWAY on its own. Are you using the latest
curl?


[1]: https://curl.se/libcurl/c/CURLOPT_MAXAGE_CONN.html
[2]: https://github.com/curl/curl/blob/curl-8_5_0/lib/url.c#L767-L777

-- 
Unsubscribe: https://lists.haxx.se/mailman/listinfo/curl-library
Etiquette:   https://curl.se/mail/etiquette.html
Received on 2024-01-05