http/3: add description for known server error codes
No binary (build failed)
—
(log yok)
| @@ -1372,7 +1372,9 @@ static CURLcode recv_closed_stream(struct Curl_cfilter *cf, | |
| (void)cf; | |
| *pnread = 0; | |
| if(stream->reset) { | |
| - | failf(data, "HTTP/3 stream %" PRId64 " reset by server", stream->id); |
| + | failf(data, "HTTP/3 stream %" PRId64 " reset by server (error 0x%" PRIx64 |
| + | " %s)", stream->id, stream->error3, |
| + | vquic_h3_err_str(stream->error3)); |
| return data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP3; | |
| } | |
| else if(!stream->resp_hds_complete) { | |
| @@ -2076,9 +2076,9 @@ static CURLcode recv_closed_stream(struct Curl_cfilter *cf, | |
| (void)cf; | |
| *pnread = 0; | |
| if(stream->reset) { | |
| - | failf(data, |
| - | "HTTP/3 stream %" PRId64 " reset by server", |
| - | stream->s.id); |
| + | failf(data, "HTTP/3 stream %" PRId64 " reset by server (error 0x%" PRIx64 |
| + | " %s)", stream->s.id, stream->error3, |
| + | vquic_h3_err_str(stream->error3)); |
| return data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP3; | |
| } | |
| else if(!stream->resp_hds_complete) { | |
| @@ -855,7 +855,9 @@ static CURLcode recv_closed_stream(struct Curl_cfilter *cf, | |
| DEBUGASSERT(stream); | |
| *pnread = 0; | |
| if(stream->reset) { | |
| - | failf(data, "HTTP/3 stream %" PRIu64 " reset by server", stream->id); |
| + | failf(data, "HTTP/3 stream %" PRId64 " reset by server (error 0x%" PRIx64 |
| + | " %s)", stream->id, stream->error3, |
| + | vquic_h3_err_str(stream->error3)); |
| result = data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP3; | |
| CURL_TRC_CF(data, cf, "[%" PRIu64 "] cf_recv, was reset -> %d", | |
| stream->id, result); | |
| @@ -742,6 +742,56 @@ CURLcode Curl_conn_may_http3(struct Curl_easy *data, | |
| return CURLE_OK; | |
| } | |
| + | #ifndef CURL_DISABLE_VERBOSE_STRINGS |
| + | const char *vquic_h3_err_str(uint64_t error_code) |
| + | { |
| + | if(error_code <= UINT_MAX) { |
| + | switch((unsigned int)error_code) { |
| + | case CURL_H3_ERR_NO_ERROR: |
| + | return "NO_ERROR"; |
| + | case CURL_H3_ERR_GENERAL_PROTOCOL_ERROR: |
| + | return "GENERAL_PROTOCOL_ERROR"; |
| + | case CURL_H3_ERR_INTERNAL_ERROR: |
| + | return "INTERNAL_ERROR"; |
| + | case CURL_H3_ERR_STREAM_CREATION_ERROR: |
| + | return "STREAM_CREATION_ERROR"; |
| + | case CURL_H3_ERR_CLOSED_CRITICAL_STREAM: |
| + | return "CLOSED_CRITICAL_STREAM"; |
| + | case CURL_H3_ERR_FRAME_UNEXPECTED: |
| + | return "FRAME_UNEXPECTED"; |
| + | case CURL_H3_ERR_FRAME_ERROR: |
| + | return "FRAME_ERROR"; |
| + | case CURL_H3_ERR_EXCESSIVE_LOAD: |
| + | return "EXCESSIVE_LOAD"; |
| + | case CURL_H3_ERR_ID_ERROR: |
| + | return "ID_ERROR"; |
| + | case CURL_H3_ERR_SETTINGS_ERROR: |
| + | return "SETTINGS_ERROR"; |
| + | case CURL_H3_ERR_MISSING_SETTINGS: |
| + | return "MISSING_SETTINGS"; |
| + | case CURL_H3_ERR_REQUEST_REJECTED: |
| + | return "REQUEST_REJECTED"; |
| + | case CURL_H3_ERR_REQUEST_CANCELLED: |
| + | return "REQUEST_CANCELLED"; |
| + | case CURL_H3_ERR_REQUEST_INCOMPLETE: |
| + | return "REQUEST_INCOMPLETE"; |
| + | case CURL_H3_ERR_MESSAGE_ERROR: |
| + | return "MESSAGE_ERROR"; |
| + | case CURL_H3_ERR_CONNECT_ERROR: |
| + | return "CONNECT_ERROR"; |
| + | case CURL_H3_ERR_VERSION_FALLBACK: |
| + | return "VERSION_FALLBACK"; |
| + | default: |
| + | break; |
| + | } |
| + | } |
| + | /* RFC 9114 ch. 8.1 + 9, reserved future error codes that are NO_ERROR */ |
| + | if((error_code >= 0x21) && !((error_code - 0x21) % 0x1f)) |
| + | return "NO_ERROR"; |
| + | return "unknown"; |
| + | } |
| + | #endif /* CURL_DISABLE_VERBOSE_STRINGS */ |
| + | |
| #if defined(USE_NGTCP2) || defined(USE_NGHTTP3) | |
| static void *vquic_ngtcp2_malloc(size_t size, void *user_data) | |
| @@ -32,6 +32,33 @@ | |
| #define MAX_PKT_BURST 10 | |
| #define MAX_UDP_PAYLOAD_SIZE 1452 | |
| + | /* definitions from RFC 9114, ch 8.1 */ |
| + | typedef enum { |
| + | CURL_H3_ERR_NO_ERROR = 0x0100, |
| + | CURL_H3_ERR_GENERAL_PROTOCOL_ERROR = 0x0101, |
| + | CURL_H3_ERR_INTERNAL_ERROR = 0x0102, |
| + | CURL_H3_ERR_STREAM_CREATION_ERROR = 0x0103, |
| + | CURL_H3_ERR_CLOSED_CRITICAL_STREAM = 0x0104, |
| + | CURL_H3_ERR_FRAME_UNEXPECTED = 0x0105, |
| + | CURL_H3_ERR_FRAME_ERROR = 0x0106, |
| + | CURL_H3_ERR_EXCESSIVE_LOAD = 0x0107, |
| + | CURL_H3_ERR_ID_ERROR = 0x0108, |
| + | CURL_H3_ERR_SETTINGS_ERROR = 0x0109, |
| + | CURL_H3_ERR_MISSING_SETTINGS = 0x010a, |
| + | CURL_H3_ERR_REQUEST_REJECTED = 0x010b, |
| + | CURL_H3_ERR_REQUEST_CANCELLED = 0x010c, |
| + | CURL_H3_ERR_REQUEST_INCOMPLETE = 0x010d, |
| + | CURL_H3_ERR_MESSAGE_ERROR = 0x010e, |
| + | CURL_H3_ERR_CONNECT_ERROR = 0x010f, |
| + | CURL_H3_ERR_VERSION_FALLBACK = 0x0110, |
| + | } vquic_h3_error; |
| + | |
| + | #ifndef CURL_DISABLE_VERBOSE_STRINGS |
| + | const char *vquic_h3_err_str(uint64_t error_code); |
| + | #else |
| + | #define vquic_h3_err_str(x) "" |
| + | #endif /* CURL_DISABLE_VERBOSE_STRINGS */ |
| + | |
| struct cf_quic_ctx { | |
| curl_socket_t sockfd; /* connected UDP socket */ | |
| struct sockaddr_storage local_addr; /* address socket is bound to */ | |