return length;
}
-static const std::unordered_map<std::string, std::string> s_constants{
- {"200-value", "200"},
- {"method-name", ":method"},
- {"method-value", "POST"},
- {"scheme-name", ":scheme"},
- {"scheme-value", "https"},
- {"authority-name", ":authority"},
- {"x-forwarded-for-name", "x-forwarded-for"},
- {"path-name", ":path"},
- {"content-length-name", "content-length"},
- {"status-name", ":status"},
- {"location-name", "location"},
- {"accept-name", "accept"},
- {"accept-value", "application/dns-message"},
- {"cache-control-name", "cache-control"},
- {"content-type-name", "content-type"},
- {"content-type-value", "application/dns-message"},
- {"user-agent-name", "user-agent"},
- {"user-agent-value", "nghttp2-" NGHTTP2_VERSION "/dnsdist"},
- {"x-forwarded-port-name", "x-forwarded-port"},
- {"x-forwarded-proto-name", "x-forwarded-proto"},
- {"x-forwarded-proto-value-dns-over-udp", "dns-over-udp"},
- {"x-forwarded-proto-value-dns-over-tcp", "dns-over-tcp"},
- {"x-forwarded-proto-value-dns-over-tls", "dns-over-tls"},
- {"x-forwarded-proto-value-dns-over-http", "dns-over-http"},
- {"x-forwarded-proto-value-dns-over-https", "dns-over-https"},
+static const std::array<const std::string, static_cast<size_t>(NGHTTP2Headers::HeaderConstantIndexes::COUNT)> s_headerConstants{
+ "200",
+ ":method",
+ "POST",
+ ":scheme",
+ "https",
+ ":authority",
+ "x-forwarded-for",
+ ":path",
+ "content-length",
+ ":status",
+ "location",
+ "accept",
+ "application/dns-message",
+ "cache-control",
+ "content-type",
+ "application/dns-message",
+ "user-agent",
+ "nghttp2-" NGHTTP2_VERSION "/dnsdist",
+ "x-forwarded-port",
+ "x-forwarded-proto",
+ "dns-over-udp",
+ "dns-over-tcp",
+ "dns-over-tls",
+ "dns-over-http",
+ "dns-over-https"
};
static const std::string s_authorityHeaderName(":authority");
static const std::string s_schemeHeaderName(":scheme");
static const std::string s_xForwardedForHeaderName("x-forwarded-for");
-void NGHTTP2Headers::addStaticHeader(std::vector<nghttp2_nv>& headers, const std::string& nameKey, const std::string& valueKey)
+void NGHTTP2Headers::addStaticHeader(std::vector<nghttp2_nv>& headers, NGHTTP2Headers::HeaderConstantIndexes nameKey, NGHTTP2Headers::HeaderConstantIndexes valueKey)
{
- const auto& name = s_constants.at(nameKey);
- const auto& value = s_constants.at(valueKey);
+ const auto& name = s_headerConstants.at(static_cast<size_t>(nameKey));
+ const auto& value = s_headerConstants.at(static_cast<size_t>(valueKey));
headers.push_back({const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(name.c_str())), const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(value.c_str())), name.size(), value.size(), NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE});
}
headers.push_back({const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(name.data())), const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(value.data())), name.size(), value.size(), NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE});
}
-void NGHTTP2Headers::addDynamicHeader(std::vector<nghttp2_nv>& headers, const std::string& nameKey, const std::string_view& value)
+void NGHTTP2Headers::addDynamicHeader(std::vector<nghttp2_nv>& headers, NGHTTP2Headers::HeaderConstantIndexes nameKey, const std::string_view& value)
{
- const auto& name = s_constants.at(nameKey);
+ const auto& name = s_headerConstants.at(static_cast<size_t>(nameKey));
NGHTTP2Headers::addCustomDynamicHeader(headers, name, value);
}
std::string location;
/* remember that dynamic header values should be kept alive
until we have called nghttp2_submit_response(), at least */
+ /* status, content-type, cache-control, content-length */
+ headers.reserve(4);
if (responseCode == 200) {
- NGHTTP2Headers::addStaticHeader(headers, "status-name", "200-value");
+ NGHTTP2Headers::addStaticHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::STATUS_NAME, NGHTTP2Headers::HeaderConstantIndexes::OK_200_VALUE);
++df->d_validresponses;
++df->d_http2Stats.d_nb200Responses;
if (addContentType) {
if (contentType.empty()) {
- NGHTTP2Headers::addStaticHeader(headers, "content-type-name", "content-type-value");
+ NGHTTP2Headers::addStaticHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::CONTENT_TYPE_NAME, NGHTTP2Headers::HeaderConstantIndexes::CONTENT_TYPE_VALUE);
}
else {
- NGHTTP2Headers::addDynamicHeader(headers, "content-type-name", contentType);
+ NGHTTP2Headers::addDynamicHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::CONTENT_TYPE_NAME, contentType);
}
}
uint32_t minTTL = getDNSPacketMinTTL(reinterpret_cast<const char*>(responseBody.data()), responseBody.size());
if (minTTL != std::numeric_limits<uint32_t>::max()) {
cacheControlValue = "max-age=" + std::to_string(minTTL);
- NGHTTP2Headers::addDynamicHeader(headers, "cache-control-name", cacheControlValue);
+ NGHTTP2Headers::addDynamicHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::CACHE_CONTROL_NAME, cacheControlValue);
}
}
}
else {
responseCodeStr = std::to_string(responseCode);
- NGHTTP2Headers::addDynamicHeader(headers, "status-name", responseCodeStr);
+ NGHTTP2Headers::addDynamicHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::STATUS_NAME, responseCodeStr);
if (responseCode >= 300 && responseCode < 400) {
location = std::string(reinterpret_cast<const char*>(responseBody.data()), responseBody.size());
- NGHTTP2Headers::addDynamicHeader(headers, "content-type-name", "text/html; charset=utf-8");
- NGHTTP2Headers::addDynamicHeader(headers, "location-name", location);
+ NGHTTP2Headers::addDynamicHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::CONTENT_TYPE_NAME, "text/html; charset=utf-8");
+ NGHTTP2Headers::addDynamicHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::LOCATION_NAME, location);
static const std::string s_redirectStart{"<!DOCTYPE html><TITLE>Moved</TITLE><P>The document has moved <A HREF=\""};
static const std::string s_redirectEnd{"\">here</A>"};
responseBody.reserve(s_redirectStart.size() + responseBody.size() + s_redirectEnd.size());
}
if (!responseBody.empty()) {
- NGHTTP2Headers::addDynamicHeader(headers, "content-type-name", "text/plain; charset=utf-8");
+ NGHTTP2Headers::addDynamicHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::CONTENT_TYPE_NAME, "text/plain; charset=utf-8");
}
else {
static const std::string invalid{"invalid DNS query"};
}
const std::string contentLength = std::to_string(responseBody.size());
- NGHTTP2Headers::addDynamicHeader(headers, "content-length-name", contentLength);
+ NGHTTP2Headers::addDynamicHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::CONTENT_LENGTH_NAME, contentLength);
for (const auto& [key, value] : customResponseHeaders) {
NGHTTP2Headers::addCustomDynamicHeader(headers, key, value);
}
IncomingHTTP2Connection* conn = reinterpret_cast<IncomingHTTP2Connection*>(user_data);
- auto insertPair = conn->d_currentStreams.insert({frame->hd.stream_id, PendingQuery()});
+ auto insertPair = conn->d_currentStreams.emplace(frame->hd.stream_id, PendingQuery());
if (!insertPair.second) {
/* there is a stream ID collision, something is very wrong! */
vinfolog("Stream ID collision (%d) on connection from %d", frame->hd.stream_id, conn->d_ci.remote.toStringWithPort());
static void handleReadableIOCallback(int fd, FDMultiplexer::funcparam_t& param);
static void handleWritableIOCallback(int fd, FDMultiplexer::funcparam_t& param);
- static void addStaticHeader(std::vector<nghttp2_nv>& headers, const std::string& nameKey, const std::string& valueKey);
- static void addDynamicHeader(std::vector<nghttp2_nv>& headers, const std::string& nameKey, const std::string& value);
-
class PendingRequest
{
public:
headers.reserve(8 + (addXForwarded ? 3 : 0));
/* Pseudo-headers need to come first (rfc7540 8.1.2.1) */
- NGHTTP2Headers::addStaticHeader(headers, "method-name", "method-value");
- NGHTTP2Headers::addStaticHeader(headers, "scheme-name", "scheme-value");
- NGHTTP2Headers::addDynamicHeader(headers, "authority-name", d_ds->d_config.d_tlsSubjectName);
- NGHTTP2Headers::addDynamicHeader(headers, "path-name", d_ds->d_config.d_dohPath);
- NGHTTP2Headers::addStaticHeader(headers, "accept-name", "accept-value");
- NGHTTP2Headers::addStaticHeader(headers, "content-type-name", "content-type-value");
- NGHTTP2Headers::addStaticHeader(headers, "user-agent-name", "user-agent-value");
- NGHTTP2Headers::addDynamicHeader(headers, "content-length-name", payloadSize);
+ NGHTTP2Headers::addStaticHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::METHOD_NAME, NGHTTP2Headers::HeaderConstantIndexes::METHOD_VALUE);
+ NGHTTP2Headers::addStaticHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::SCHEME_NAME, NGHTTP2Headers::HeaderConstantIndexes::SCHEME_VALUE);
+ NGHTTP2Headers::addDynamicHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::AUTHORITY_NAME, d_ds->d_config.d_tlsSubjectName);
+ NGHTTP2Headers::addDynamicHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::PATH_NAME, d_ds->d_config.d_dohPath);
+ NGHTTP2Headers::addStaticHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::ACCEPT_NAME, NGHTTP2Headers::HeaderConstantIndexes::ACCEPT_VALUE);
+ NGHTTP2Headers::addStaticHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::CONTENT_TYPE_NAME, NGHTTP2Headers::HeaderConstantIndexes::CONTENT_TYPE_VALUE);
+ NGHTTP2Headers::addStaticHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::USER_AGENT_NAME, NGHTTP2Headers::HeaderConstantIndexes::USER_AGENT_VALUE);
+ NGHTTP2Headers::addDynamicHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::CONTENT_LENGTH_NAME, payloadSize);
/* no need to add these headers for health-check queries */
if (addXForwarded && query.d_idstate.origRemote.getPort() != 0) {
remote = query.d_idstate.origRemote.toString();
remotePort = std::to_string(query.d_idstate.origRemote.getPort());
- NGHTTP2Headers::addDynamicHeader(headers, "x-forwarded-for-name", remote);
- NGHTTP2Headers::addDynamicHeader(headers, "x-forwarded-port-name", remotePort);
+ NGHTTP2Headers::addDynamicHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::X_FORWARDED_FOR_NAME, remote);
+ NGHTTP2Headers::addDynamicHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::X_FORWARDED_PORT_NAME, remotePort);
if (query.d_idstate.cs != nullptr) {
if (query.d_idstate.cs->isUDP()) {
- NGHTTP2Headers::addStaticHeader(headers, "x-forwarded-proto-name", "x-forwarded-proto-value-dns-over-udp");
+ NGHTTP2Headers::addStaticHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::X_FORWARDED_PROTO_NAME, NGHTTP2Headers::HeaderConstantIndexes::X_FORWARDED_PROTO_VALUE_DNS_OVER_UDP);
}
else if (query.d_idstate.cs->isDoH()) {
if (query.d_idstate.cs->hasTLS()) {
- NGHTTP2Headers::addStaticHeader(headers, "x-forwarded-proto-name", "x-forwarded-proto-value-dns-over-https");
+ NGHTTP2Headers::addStaticHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::X_FORWARDED_PROTO_NAME, NGHTTP2Headers::HeaderConstantIndexes::X_FORWARDED_PROTO_VALUE_DNS_OVER_HTTPS);
}
else {
- NGHTTP2Headers::addStaticHeader(headers, "x-forwarded-proto-name", "x-forwarded-proto-value-dns-over-http");
+ NGHTTP2Headers::addStaticHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::X_FORWARDED_PROTO_NAME, NGHTTP2Headers::HeaderConstantIndexes::X_FORWARDED_PROTO_VALUE_DNS_OVER_HTTP);
}
}
else if (query.d_idstate.cs->hasTLS()) {
- NGHTTP2Headers::addStaticHeader(headers, "x-forwarded-proto-name", "x-forwarded-proto-value-dns-over-tls");
+ NGHTTP2Headers::addStaticHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::X_FORWARDED_PROTO_NAME, NGHTTP2Headers::HeaderConstantIndexes::X_FORWARDED_PROTO_VALUE_DNS_OVER_TLS);
}
else {
- NGHTTP2Headers::addStaticHeader(headers, "x-forwarded-proto-name", "x-forwarded-proto-value-dns-over-tcp");
+ NGHTTP2Headers::addStaticHeader(headers, NGHTTP2Headers::HeaderConstantIndexes::X_FORWARDED_PROTO_NAME, NGHTTP2Headers::HeaderConstantIndexes::X_FORWARDED_PROTO_VALUE_DNS_OVER_TCP);
}
}
}