(((namelen) == sizeof(header) - 1) && \
(strncasecmp((header), (const char *)(name), (namelen)) == 0))
+#define MIN_SUCCESSFUL_HTTP_STATUS (200)
+#define MAX_SUCCESSFUL_HTTP_STATUS (299)
+
+#define SUCCESSFUL_HTTP_STATUS(code) \
+ ((code) >= MIN_SUCCESSFUL_HTTP_STATUS && \
+ (code) <= MAX_SUCCESSFUL_HTTP_STATUS)
+
typedef struct isc_nm_http_response_status {
size_t code;
size_t content_length;
return (rv);
}
+static void
+call_unlink_cstream_readcb(http_cstream_t *cstream,
+ isc_nm_http_session_t *session,
+ isc_result_t result) {
+ REQUIRE(VALID_HTTP2_SESSION(session));
+ REQUIRE(cstream != NULL);
+ cstream->read_cb(session->handle, result,
+ &(isc_region_t){ cstream->rbuf, cstream->rbufsize },
+ cstream->read_cbarg);
+ ISC_LIST_UNLINK(session->cstreams, cstream, link);
+ put_http_cstream(session->mctx, cstream);
+}
+
static int
on_client_stream_close_callback(int32_t stream_id,
isc_nm_http_session_t *session) {
if (cstream != NULL) {
isc_result_t result =
- cstream->response_status.code >= 200 &&
- cstream->response_status.code < 300
+ SUCCESSFUL_HTTP_STATUS(cstream->response_status.code)
? ISC_R_SUCCESS
: ISC_R_FAILURE;
- cstream->read_cb(
- session->handle, result,
- &(isc_region_t){ cstream->rbuf, cstream->rbufsize },
- cstream->read_cbarg);
- ISC_LIST_UNLINK(session->cstreams, cstream, link);
- put_http_cstream(session->mctx, cstream);
+ call_unlink_cstream_readcb(cstream, session, result);
if (ISC_LIST_EMPTY(session->cstreams)) {
int rv = 0;
rv = nghttp2_session_terminate_session(
return (rv);
}
-static void
+static bool
client_handle_status_header(http_cstream_t *cstream, const uint8_t *value,
const size_t valuelen) {
char tmp[32] = { 0 };
strncpy(tmp, (const char *)value, ISC_MIN(tmplen, valuelen));
cstream->response_status.code = strtoul(tmp, NULL, 10);
+
+ if (SUCCESSFUL_HTTP_STATUS(cstream->response_status.code)) {
+ return (true);
+ }
+
+ return (false);
}
-static void
+static bool
client_handle_content_length_header(http_cstream_t *cstream,
const uint8_t *value,
const size_t valuelen) {
strncpy(tmp, (const char *)value, ISC_MIN(tmplen, valuelen));
cstream->response_status.content_length = strtoul(tmp, NULL, 10);
+
+ if (cstream->response_status.content_length == 0 ||
+ cstream->response_status.content_length > MAX_DNS_MESSAGE_SIZE)
+ {
+ return (false);
+ }
+
+ return (true);
}
-static void
+static bool
client_handle_content_type_header(http_cstream_t *cstream, const uint8_t *value,
const size_t valuelen) {
const char type_dns_message[] = DNS_MEDIA_TYPE;
if (strncasecmp((const char *)value, type_dns_message, len) == 0) {
cstream->response_status.content_type_valid = true;
+ return (true);
}
+
+ return (false);
}
static int
const char status[] = ":status";
const char content_length[] = "Content-Length";
const char content_type[] = "Content-Type";
+ bool header_ok = true;
REQUIRE(VALID_HTTP2_SESSION(session));
REQUIRE(session->client);
}
if (HEADER_MATCH(status, name, namelen)) {
- client_handle_status_header(cstream, value, valuelen);
+ header_ok = client_handle_status_header(cstream, value,
+ valuelen);
} else if (HEADER_MATCH(content_length, name, namelen)) {
- client_handle_content_length_header(cstream, value,
- valuelen);
+ header_ok = client_handle_content_length_header(
+ cstream, value, valuelen);
} else if (HEADER_MATCH(content_type, name, namelen)) {
- client_handle_content_type_header(cstream, value,
- valuelen);
- if (!cstream->response_status.content_type_valid) {
- return (NGHTTP2_ERR_HTTP_HEADER);
- }
+ header_ok = client_handle_content_type_header(
+ cstream, value, valuelen);
}
break;
}
+ if (!header_ok) {
+ return (NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE);
+ }
+
return (0);
}