From b71bc694c8a08804714a9469a48f58dac5dd96cb Mon Sep 17 00:00:00 2001 From: Jay Satiro Date: Thu, 3 Mar 2016 00:47:46 -0500 Subject: http2: Add Curl_http2_strerror for HTTP/2 error codes Ref: https://github.com/curl/curl/issues/659 Ref: https://github.com/curl/curl/pull/663 --- lib/http2.c | 41 +++++++++++++++++++++++++++++++++++++---- lib/http2.h | 2 ++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/lib/http2.c b/lib/http2.c index 73470f8e7..f9e873ac6 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -46,6 +46,10 @@ #error too old nghttp2 version, upgrade! #endif +#if (NGHTTP2_VERSION_NUM > 0x010800) +#define NGHTTP2_HAS_HTTP2_STRERROR 1 +#endif + #if (NGHTTP2_VERSION_NUM >= 0x010900) /* nghttp2_session_callbacks_set_error_callback is present in nghttp2 1.9.0 or later */ @@ -212,6 +216,34 @@ int Curl_http2_ver(char *p, size_t len) return snprintf(p, len, " nghttp2/%s", h2->version_str); } +/* HTTP/2 error code to name based on the Error Code Registry. +https://tools.ietf.org/html/rfc7540#page-77 +nghttp2_error_code enums are identical. +*/ +const char *Curl_http2_strerror(uint32_t err) { +#ifndef NGHTTP2_HAS_HTTP2_STRERROR + const char *str[] = { + "NO_ERROR", /* 0x0 */ + "PROTOCOL_ERROR", /* 0x1 */ + "INTERNAL_ERROR", /* 0x2 */ + "FLOW_CONTROL_ERROR", /* 0x3 */ + "SETTINGS_TIMEOUT", /* 0x4 */ + "STREAM_CLOSED", /* 0x5 */ + "FRAME_SIZE_ERROR", /* 0x6 */ + "REFUSED_STREAM", /* 0x7 */ + "CANCEL", /* 0x8 */ + "COMPRESSION_ERROR", /* 0x9 */ + "CONNECT_ERROR", /* 0xA */ + "ENHANCE_YOUR_CALM", /* 0xB */ + "INADEQUATE_SECURITY", /* 0xC */ + "HTTP_1_1_REQUIRED" /* 0xD */ + }; + return (err < sizeof str / sizeof str[0]) ? str[err] : "unknown"; +#else + return nghttp2_http2_strerror(err); +#endif +} + /* * The implementation of nghttp2_send_callback type. Here we write |data| with * size |length| to the network and return the number of bytes actually @@ -680,8 +712,8 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id, decided to reject stream (e.g., PUSH_PROMISE). */ return 0; } - DEBUGF(infof(data_s, "on_stream_close(), error_code = %d, stream %u\n", - error_code, stream_id)); + DEBUGF(infof(data_s, "on_stream_close(), %s (err %d), stream %u\n", + Curl_http2_strerror(error_code), error_code, stream_id)); stream = data_s->req.protop; if(!stream) return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -1148,8 +1180,9 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, function. */ stream->closed = FALSE; if(stream->error_code != NGHTTP2_NO_ERROR) { - failf(data, "HTTP/2 stream %u was not closed cleanly: error_code = %d", - stream->stream_id, stream->error_code); + failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %d)", + stream->stream_id, Curl_http2_strerror(stream->error_code), + stream->error_code); *err = CURLE_HTTP2_STREAM; return -1; } diff --git a/lib/http2.h b/lib/http2.h index 2d073347e..1aec30403 100644 --- a/lib/http2.h +++ b/lib/http2.h @@ -37,6 +37,8 @@ */ int Curl_http2_ver(char *p, size_t len); +const char *Curl_http2_strerror(uint32_t err); + CURLcode Curl_http2_init(struct connectdata *conn); void Curl_http2_init_state(struct UrlState *state); void Curl_http2_init_userset(struct UserDefined *set); -- cgit v1.2.3