summaryrefslogtreecommitdiffstats
path: root/src/output/dnssim/https2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/output/dnssim/https2.c')
-rw-r--r--src/output/dnssim/https2.c592
1 files changed, 0 insertions, 592 deletions
diff --git a/src/output/dnssim/https2.c b/src/output/dnssim/https2.c
deleted file mode 100644
index 72fcdaf..0000000
--- a/src/output/dnssim/https2.c
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- * Copyright (c) 2020, CZ.NIC, z.s.p.o.
- * All rights reserved.
- *
- * This file is part of dnsjit.
- *
- * dnsjit is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * dnsjit is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with dnsjit. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include "output/dnssim.h"
-#include "output/dnssim/internal.h"
-#include "output/dnssim/ll.h"
-#include "core/assert.h"
-#include "lib/base64url.h"
-
-#include <gnutls/gnutls.h>
-#include <string.h>
-
-#if GNUTLS_VERSION_NUMBER >= DNSSIM_MIN_GNUTLS_VERSION
-
-#define OUTPUT_DNSSIM_MAKE_NV(NAME, VALUE, VALUELEN) \
- { \
- (uint8_t*)NAME, (uint8_t*)VALUE, sizeof(NAME) - 1, VALUELEN, \
- NGHTTP2_NV_FLAG_NONE \
- }
-
-#define OUTPUT_DNSSIM_MAKE_NV2(NAME, VALUE) \
- { \
- (uint8_t*)NAME, (uint8_t*)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
- NGHTTP2_NV_FLAG_NONE \
- }
-
-#define OUTPUT_DNSSIM_HTTP_GET_TEMPLATE "?dns="
-#define OUTPUT_DNSSIM_HTTP_GET_TEMPLATE_LEN (sizeof(OUTPUT_DNSSIM_HTTP_GET_TEMPLATE) - 1)
-#define OUTPUT_DNSSIM_HTTP2_INITIAL_MAX_CONCURRENT_STREAMS 100
-#define OUTPUT_DNSSIM_HTTP2_DEFAULT_MAX_CONCURRENT_STREAMS 0xffffffffu
-
-static core_log_t _log = LOG_T_INIT("output.dnssim");
-
-static ssize_t _http2_send(nghttp2_session* session, const uint8_t* data, size_t length, int flags, void* user_data)
-{
- _output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)user_data;
- mlassert(conn, "conn can't be null");
- mlassert(conn->tls, "conn must have tls ctx");
- mlassert(conn->tls->session, "conn must have tls session");
-
- mldebug("http2 (%p): sending data, len=%ld", session, length);
-
- ssize_t len = 0;
- if ((len = gnutls_record_send(conn->tls->session, data, length)) < 0) {
- mlwarning("gnutls_record_send failed: %s", gnutls_strerror(len));
- len = NGHTTP2_ERR_CALLBACK_FAILURE;
- }
-
- return len;
-}
-
-static ssize_t _http2_on_data_provider_read(nghttp2_session* session, int32_t stream_id, uint8_t* buf, size_t length, uint32_t* data_flags, nghttp2_data_source* source, void* user_data)
-{
- _output_dnssim_https2_data_provider_t* buffer = source->ptr;
- mlassert(buffer, "no data provider");
- mlassert(buffer->len <= MAX_DNSMSG_SIZE, "invalid dnsmsg size: %zu B", buffer->len);
-
- ssize_t sent = (length < buffer->len) ? length : buffer->len;
- mlassert(sent >= 0, "negative length of bytes to send");
-
- memcpy(buf, buffer->buf, sent);
- buffer->buf += sent;
- buffer->len -= sent;
- if (buffer->len == 0)
- *data_flags |= NGHTTP2_DATA_FLAG_EOF;
-
- return sent;
-}
-
-static _output_dnssim_query_tcp_t* _http2_get_stream_qry(_output_dnssim_connection_t* conn, int32_t stream_id)
-{
- mlassert(conn, "conn is nil");
- mlassert(stream_id >= 0, "invalid stream_id");
-
- _output_dnssim_query_tcp_t* qry = (_output_dnssim_query_tcp_t*)conn->sent;
- while (qry != NULL && qry->stream_id != stream_id) {
- qry = (_output_dnssim_query_tcp_t*)qry->qry.next;
- }
-
- return qry;
-}
-
-static int _http2_on_header(nghttp2_session* session, const nghttp2_frame* frame, const uint8_t* name, size_t namelen, const uint8_t* value, size_t valuelen, uint8_t flags, void* user_data)
-{
- if (frame->hd.type == NGHTTP2_HEADERS && frame->headers.cat == NGHTTP2_HCAT_RESPONSE) {
- if (namelen == 7 && strncmp((char*)name, ":status", 7) == 0) {
- if (valuelen != 3 || (value[0] != '1' && value[0] != '2')) {
- /* When reponse code isn't 1xx or 2xx, close the query.
- * This will result in request timeout, which currently seems
- * slightly better than mocking SERVFAIL for statistics. */
- _output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)user_data;
- mlassert(conn, "conn is nil");
- _output_dnssim_query_tcp_t* qry = _http2_get_stream_qry(conn, frame->hd.stream_id);
-
- if (qry != NULL) {
- _output_dnssim_close_query_https2(qry);
- mlinfo("http response %s, closing query", value);
- }
- }
- }
- }
- return 0;
-}
-
-static int _http2_on_data_recv(nghttp2_session* session, uint8_t flags, int32_t stream_id, const uint8_t* data, size_t len, void* user_data)
-{
- _output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)user_data;
- mlassert(conn, "conn is nil");
-
- _output_dnssim_query_tcp_t* qry = _http2_get_stream_qry(conn, stream_id);
-
- mldebug("http2: data chunk recv, session=%p, len=%d", session, len);
-
- if (qry) {
- if (qry->recv_buf_len == 0) {
- if (len > MAX_DNSMSG_SIZE) {
- mlwarning("http response exceeded maximum size of dns message");
- return -1;
- }
- mlfatal_oom(qry->recv_buf = malloc(len));
- memcpy(qry->recv_buf, data, len);
- qry->recv_buf_len = len;
- } else {
- size_t total_len = qry->recv_buf_len + len;
- if (total_len > MAX_DNSMSG_SIZE) {
- mlwarning("http response exceeded maximum size of dns message");
- return -1;
- }
- mlfatal_oom(qry->recv_buf = realloc(qry->recv_buf, total_len));
- memcpy(qry->recv_buf + qry->recv_buf_len, data, len);
- qry->recv_buf_len = total_len;
- }
- } else {
- mldebug("no query associated with this stream id, ignoring");
- }
-
- return 0;
-}
-
-static void _http2_check_max_streams(_output_dnssim_connection_t* conn)
-{
- mlassert(conn, "conn can't be null");
- mlassert(conn->http2, "conn must have http2 ctx");
-
- switch (conn->state) {
- case _OUTPUT_DNSSIM_CONN_ACTIVE:
- if (conn->http2->open_streams >= conn->http2->max_concurrent_streams) {
- mlinfo("http2 (%p): reached maximum number of concurrent streams (%ld)",
- conn->http2->session, conn->http2->max_concurrent_streams);
- conn->state = _OUTPUT_DNSSIM_CONN_CONGESTED;
- }
- break;
- case _OUTPUT_DNSSIM_CONN_CONGESTED:
- if (conn->http2->open_streams < conn->http2->max_concurrent_streams)
- conn->state = _OUTPUT_DNSSIM_CONN_ACTIVE;
- break;
- default:
- break;
- }
-}
-
-static int _http2_on_stream_close(nghttp2_session* session, int32_t stream_id, uint32_t error_code, void* user_data)
-{
- _output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)user_data;
- mlassert(conn, "conn can't be null");
- mlassert(conn->http2, "conn must have http2 ctx");
- mlassert(conn->http2->open_streams > 0, "conn has no open streams");
-
- conn->http2->open_streams--;
- _http2_check_max_streams(conn);
- return 0;
-}
-
-static int _http2_on_frame_recv(nghttp2_session* session, const nghttp2_frame* frame, void* user_data)
-{
- _output_dnssim_connection_t* conn = (_output_dnssim_connection_t*)user_data;
- mlassert(conn, "conn can't be null");
- mlassert(conn->tls, "conn must have tls ctx");
- mlassert(conn->tls->session, "conn must have tls session");
- mlassert(conn->http2, "conn must have http2 ctx");
-
- switch (frame->hd.type) {
- case NGHTTP2_DATA:
- if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
- mldebug("http2 (%p): final DATA frame recv", session);
- _output_dnssim_query_tcp_t* qry = _http2_get_stream_qry(conn, frame->hd.stream_id);
-
- if (qry != NULL) {
- conn->http2->current_qry = qry;
- _output_dnssim_read_dnsmsg(conn, qry->recv_buf_len, (char*)qry->recv_buf);
- }
- }
- break;
- case NGHTTP2_SETTINGS:
- if (!conn->http2->remote_settings_received) {
- /* On the first SETTINGS frame, set concurrent streams to unlimited, same as nghttp2. */
- conn->http2->remote_settings_received = true;
- conn->http2->max_concurrent_streams = OUTPUT_DNSSIM_HTTP2_DEFAULT_MAX_CONCURRENT_STREAMS;
- _http2_check_max_streams(conn);
- }
- nghttp2_settings* settings = (nghttp2_settings*)frame;
- int i;
- for (i = 0; i < settings->niv; i++) {
- switch (settings->iv[i].settings_id) {
- case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
- conn->http2->max_concurrent_streams = settings->iv[i].value;
- _http2_check_max_streams(conn);
- break;
- default:
- break;
- }
- }
- break;
- default:
- break;
- }
- return 0;
-}
-
-int _output_dnssim_https2_init(_output_dnssim_connection_t* conn)
-{
- mlassert(conn, "conn is nil");
- mlassert(conn->tls == NULL, "conn already has tls context");
- mlassert(conn->http2 == NULL, "conn already has http2 context");
- mlassert(conn->client, "conn must be associated with a client");
- mlassert(conn->client->dnssim, "client must have dnssim");
-
- int ret = -1;
- nghttp2_session_callbacks* callbacks;
- nghttp2_option* option;
- output_dnssim_t* self = conn->client->dnssim;
-
- /* Initialize TLS session. */
- ret = _output_dnssim_tls_init(conn);
- if (ret < 0)
- return ret;
-
- /* Configure ALPN to negotiate HTTP/2. */
- const gnutls_datum_t protos[] = {
- { (unsigned char*)"h2", 2 }
- };
- ret = gnutls_alpn_set_protocols(conn->tls->session, protos, 1, 0);
- if (ret < 0) {
- lwarning("failed to set ALPN protocol: %s", gnutls_strerror(ret));
- return ret;
- }
-
- lfatal_oom(conn->http2 = calloc(1, sizeof(_output_dnssim_http2_ctx_t)));
- conn->http2->max_concurrent_streams = OUTPUT_DNSSIM_HTTP2_INITIAL_MAX_CONCURRENT_STREAMS;
-
- /* Set up HTTP/2 callbacks and client. */
- lassert(nghttp2_session_callbacks_new(&callbacks) == 0, "out of memory");
- nghttp2_session_callbacks_set_send_callback(callbacks, _http2_send);
- nghttp2_session_callbacks_set_on_header_callback(callbacks, _http2_on_header);
- nghttp2_session_callbacks_set_on_data_chunk_recv_callback(callbacks, _http2_on_data_recv);
- nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks, _http2_on_frame_recv);
- nghttp2_session_callbacks_set_on_stream_close_callback(callbacks, _http2_on_stream_close);
-
- lassert(nghttp2_option_new(&option) == 0, "out of memory");
- nghttp2_option_set_peer_max_concurrent_streams(option, conn->http2->max_concurrent_streams);
-
- ret = nghttp2_session_client_new2(&conn->http2->session, callbacks, conn, option);
-
- nghttp2_session_callbacks_del(callbacks);
- nghttp2_option_del(option);
-
- if (ret < 0) {
- free(conn->http2);
- conn->http2 = NULL;
- }
-
- return ret;
-}
-
-int _output_dnssim_https2_setup(_output_dnssim_connection_t* conn)
-{
- mlassert(conn, "conn is nil");
- mlassert(conn->tls, "conn must have tls ctx");
- mlassert(conn->tls->session, "conn must have tls session");
- mlassert(conn->http2, "conn must have http2 ctx");
- mlassert(conn->http2->session, "conn must have http2 session");
-
- int ret = -1;
-
- /* Check "h2" protocol was negotiated with ALPN. */
- gnutls_datum_t proto;
- ret = gnutls_alpn_get_selected_protocol(conn->tls->session, &proto);
- if (ret < 0) {
- mlwarning("http2: failed to get negotiated protocol: %s", gnutls_strerror(ret));
- return ret;
- }
- if (proto.size != 2 || memcmp("h2", proto.data, 2) != 0) {
- mlwarning("http2: protocol is not negotiated");
- return ret;
- }
-
- /* Submit SETTIGNS frame. */
- static const nghttp2_settings_entry iv[] = {
- { NGHTTP2_SETTINGS_MAX_FRAME_SIZE, MAX_DNSMSG_SIZE },
- { NGHTTP2_SETTINGS_ENABLE_PUSH, 0 }, /* Only we can initiate streams. */
- };
- ret = nghttp2_submit_settings(conn->http2->session, NGHTTP2_FLAG_NONE, iv, sizeof(iv) / sizeof(*iv));
- if (ret < 0) {
- mlwarning("http2: failed to submit SETTINGS: %s", nghttp2_strerror(ret));
- return ret;
- }
-
- ret = 0;
- return ret;
-}
-
-void _output_dnssim_https2_process_input_data(_output_dnssim_connection_t* conn, size_t len, const char* data)
-{
- mlassert(conn, "conn is nil");
- mlassert(conn->http2, "conn must have http2 ctx");
- mlassert(conn->http2->session, "conn must have http2 session");
-
- /* Process incoming frames. */
- ssize_t ret = 0;
- conn->prevent_close = true;
- ret = nghttp2_session_mem_recv(conn->http2->session, (uint8_t*)data, len);
- conn->prevent_close = false;
- if (ret < 0) {
- mlwarning("failed nghttp2_session_mem_recv: %s", nghttp2_strerror(ret));
- _output_dnssim_conn_close(conn);
- return;
- } else if (conn->state == _OUTPUT_DNSSIM_CONN_CLOSE_REQUESTED) {
- _output_dnssim_conn_close(conn);
- return;
- }
- mlassert(ret == len, "nghttp2_session_mem_recv didn't process all data");
-
- /* Send any frames the read might have triggered. */
- ret = nghttp2_session_send(conn->http2->session);
- if (ret < 0) {
- mlwarning("failed nghttp2_session_send: %s", nghttp2_strerror(ret));
- _output_dnssim_conn_close(conn);
- return;
- }
-}
-
-int _output_dnssim_create_query_https2(output_dnssim_t* self, _output_dnssim_request_t* req)
-{
- mlassert_self();
- lassert(req, "req is nil");
- lassert(req->client, "request must have a client associated with it");
-
- _output_dnssim_query_tcp_t* qry;
-
- lfatal_oom(qry = calloc(1, sizeof(_output_dnssim_query_tcp_t)));
-
- qry->qry.transport = OUTPUT_DNSSIM_TRANSPORT_HTTPS2;
- qry->qry.req = req;
- qry->qry.state = _OUTPUT_DNSSIM_QUERY_PENDING_WRITE;
- qry->stream_id = -1;
- req->qry = &qry->qry; // TODO change when adding support for multiple Qs for req
- _ll_append(req->client->pending, &qry->qry);
-
- return _output_dnssim_handle_pending_queries(req->client);
-}
-
-void _output_dnssim_close_query_https2(_output_dnssim_query_tcp_t* qry)
-{
- mlassert(qry, "qry can't be null");
- mlassert(qry->qry.req, "query must be part of a request");
- _output_dnssim_request_t* req = qry->qry.req;
- mlassert(req->client, "request must belong to a client");
-
- _ll_try_remove(req->client->pending, &qry->qry);
- if (qry->conn) {
- _output_dnssim_connection_t* conn = qry->conn;
- _ll_try_remove(conn->sent, &qry->qry);
- qry->conn = NULL;
- _output_dnssim_conn_idle(conn);
- }
-
- if (qry->recv_buf != NULL)
- free(qry->recv_buf);
-
- _ll_remove(req->qry, &qry->qry);
- free(qry);
-}
-
-void _output_dnssim_https2_close(_output_dnssim_connection_t* conn)
-{
- mlassert(conn, "conn can't be nil");
- mlassert(conn->http2, "conn must have http2 ctx");
-
- nghttp2_session_del(conn->http2->session);
- _output_dnssim_tls_close(conn);
-}
-
-static int _http2_send_query_get(_output_dnssim_connection_t* conn, _output_dnssim_query_tcp_t* qry)
-{
- mlassert(conn, "conn can't be null");
- mlassert(qry, "qry can't be null");
- mlassert(qry->qry.req, "req can't be null");
- mlassert(qry->qry.req->payload, "payload can't be null");
- mlassert(qry->qry.req->payload->len <= MAX_DNSMSG_SIZE, "payload too big");
- mlassert(conn->client, "conn must be associated with client");
- mlassert(conn->client->dnssim, "client must have dnssim");
-
- output_dnssim_t* self = conn->client->dnssim;
- core_object_payload_t* content = qry->qry.req->payload;
-
- const size_t uri_path_len = strlen(_self->h2_uri_path);
- const size_t path_len = uri_path_len
- + OUTPUT_DNSSIM_HTTP_GET_TEMPLATE_LEN
- + (content->len * 4) / 3 + 3 /* upper limit of base64 encoding */
- + 1; /* terminating null byte */
- if (path_len >= _MAX_URI_LEN) {
- self->discarded++;
- linfo("http2: uri path with query too long, query discarded");
- return 0;
- }
- char path[path_len];
- memcpy(path, _self->h2_uri_path, uri_path_len);
- memcpy(&path[uri_path_len], OUTPUT_DNSSIM_HTTP_GET_TEMPLATE, OUTPUT_DNSSIM_HTTP_GET_TEMPLATE_LEN);
-
- int32_t ret = base64url_encode(content->payload, content->len,
- (uint8_t*)&path[uri_path_len + OUTPUT_DNSSIM_HTTP_GET_TEMPLATE_LEN],
- sizeof(path) - uri_path_len - OUTPUT_DNSSIM_HTTP_GET_TEMPLATE_LEN - 1);
- if (ret < 0) {
- self->discarded++;
- linfo("http2: base64url encode of query failed, query discarded");
- return 0;
- }
-
- nghttp2_nv hdrs[] = {
- OUTPUT_DNSSIM_MAKE_NV2(":method", "GET"),
- OUTPUT_DNSSIM_MAKE_NV2(":scheme", "https"),
- OUTPUT_DNSSIM_MAKE_NV(":authority", _self->h2_uri_authority, strlen(_self->h2_uri_authority)),
- OUTPUT_DNSSIM_MAKE_NV(":path", path, uri_path_len + sizeof(OUTPUT_DNSSIM_HTTP_GET_TEMPLATE) - 1 + ret),
- OUTPUT_DNSSIM_MAKE_NV2("accept", "application/dns-message"),
- };
-
- qry->stream_id = nghttp2_submit_request(conn->http2->session, NULL, hdrs, sizeof(hdrs) / sizeof(nghttp2_nv), NULL, NULL);
-
- if (qry->stream_id < 0) {
- mldebug("http2 (%p): failed to submit request: %s", conn->http2->session, nghttp2_strerror(qry->stream_id));
- return -1;
- }
- mldebug("http2 (%p): GET %s", conn->http2->session, path);
- conn->http2->open_streams++;
- _http2_check_max_streams(conn);
-
- ret = nghttp2_session_send(conn->http2->session);
- if (ret < 0) {
- mldebug("http2 (%p): failed session send: %s", conn->http2->session, nghttp2_strerror(ret));
- return -1;
- }
-
- return 0;
-}
-
-static int _http2_send_query_post(_output_dnssim_connection_t* conn, _output_dnssim_query_tcp_t* qry)
-{
- mlassert(conn, "conn can't be null");
- mlassert(qry, "qry can't be null");
- mlassert(qry->qry.req, "req can't be null");
- mlassert(qry->qry.req->payload, "payload can't be null");
- mlassert(qry->qry.req->payload->len <= MAX_DNSMSG_SIZE, "payload too big");
- mlassert(conn->client, "conn must be associated with client");
- mlassert(conn->client->dnssim, "client must have dnssim");
-
- output_dnssim_t* self = conn->client->dnssim;
-
- core_object_payload_t* content = qry->qry.req->payload;
-
- int window_size = nghttp2_session_get_remote_window_size(conn->http2->session);
- if (content->len > window_size) {
- mldebug("http2 (%p): insufficient remote window size, deferring", conn->http2->session);
- return 0;
- }
-
- char content_length[6]; /* max dnslen "65535" */
- int content_length_len = snprintf(content_length, 6, "%zd", content->len);
-
- nghttp2_nv hdrs[] = {
- OUTPUT_DNSSIM_MAKE_NV2(":method", "POST"),
- OUTPUT_DNSSIM_MAKE_NV2(":scheme", "https"),
- OUTPUT_DNSSIM_MAKE_NV(":authority", _self->h2_uri_authority, strlen(_self->h2_uri_authority)),
- OUTPUT_DNSSIM_MAKE_NV(":path", _self->h2_uri_path, strlen(_self->h2_uri_path)),
- OUTPUT_DNSSIM_MAKE_NV2("accept", "application/dns-message"),
- OUTPUT_DNSSIM_MAKE_NV2("content-type", "application/dns-message"),
- OUTPUT_DNSSIM_MAKE_NV("content-length", content_length, content_length_len)
- };
-
- _output_dnssim_https2_data_provider_t data = {
- .buf = content->payload,
- .len = content->len
- };
-
- nghttp2_data_provider data_provider = {
- .source.ptr = &data,
- .read_callback = _http2_on_data_provider_read
- };
-
- qry->stream_id = nghttp2_submit_request(conn->http2->session, NULL, hdrs, sizeof(hdrs) / sizeof(nghttp2_nv), &data_provider, NULL);
-
- if (qry->stream_id < 0) {
- mldebug("http2 (%p): failed to submit request: %s", conn->http2->session, nghttp2_strerror(qry->stream_id));
- return -1;
- }
- mldebug("http2 (%p): POST payload len=%ld", conn->http2->session, content->len);
- conn->http2->open_streams++;
- _http2_check_max_streams(conn);
-
- window_size = nghttp2_session_get_stream_remote_window_size(conn->http2->session, qry->stream_id);
- mlassert(content->len <= window_size,
- "unsupported: http2 stream window size (%ld B) is smaller than dns payload (%ld B)",
- window_size, content->len);
-
- int ret = nghttp2_session_send(conn->http2->session);
- if (ret < 0) {
- mldebug("http2 (%p): failed session send: %s", conn->http2->session, nghttp2_strerror(ret));
- return -1;
- }
-
- return 0;
-}
-
-void _output_dnssim_https2_write_query(_output_dnssim_connection_t* conn, _output_dnssim_query_tcp_t* qry)
-{
- mlassert(qry, "qry can't be null");
- mlassert(qry->qry.state == _OUTPUT_DNSSIM_QUERY_PENDING_WRITE, "qry must be pending write");
- mlassert(conn, "conn can't be null");
- mlassert(conn->state == _OUTPUT_DNSSIM_CONN_ACTIVE, "connection state != ACTIVE");
- mlassert(conn->http2, "conn must have http2 ctx");
- mlassert(conn->http2->session, "conn must have http2 session");
- mlassert(conn->client, "conn must be associated with client");
- mlassert(conn->client->pending, "conn has no pending queries");
- mlassert(conn->client->dnssim, "client must have dnssim");
-
- int ret = 0;
- output_dnssim_t* self = conn->client->dnssim;
-
- if (!nghttp2_session_check_request_allowed(conn->http2->session)) {
- mldebug("http2 (%p): request not allowed", conn->http2->session);
- _output_dnssim_conn_close(conn);
- return;
- }
-
- switch (_self->h2_method) {
- case OUTPUT_DNSSIM_H2_POST:
- ret = _http2_send_query_post(conn, qry);
- break;
- case OUTPUT_DNSSIM_H2_GET:
- ret = _http2_send_query_get(conn, qry);
- break;
- default:
- lfatal("http2: unsupported method");
- }
-
- if (ret < 0) {
- _output_dnssim_conn_close(conn);
- return;
- }
-
- qry->conn = conn;
- _ll_remove(conn->client->pending, &qry->qry);
- _ll_append(conn->sent, &qry->qry);
-
- /* Stop idle timer, since there are queries to answer now. */
- if (conn->idle_timer != NULL) {
- conn->is_idle = false;
- uv_timer_stop(conn->idle_timer);
- }
-
- qry->qry.state = _OUTPUT_DNSSIM_QUERY_SENT;
-}
-
-#endif