]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnsdistdist/dnsdist-nghttp2-in.hh
Merge pull request #11431 from jroessler-ox/docs-kskzskroll-update
[thirdparty/pdns.git] / pdns / dnsdistdist / dnsdist-nghttp2-in.hh
1 /*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22 #pragma once
23
24 #include "config.h"
25 #if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
26 #include <nghttp2/nghttp2.h>
27
28 #include "dnsdist-tcp-upstream.hh"
29
30 class IncomingHTTP2Connection : public IncomingTCPConnectionState
31 {
32 public:
33 using StreamID = int32_t;
34
35 class PendingQuery
36 {
37 public:
38 enum class Method : uint8_t
39 {
40 Unknown,
41 Get,
42 Post,
43 Unsupported
44 };
45
46 PacketBuffer d_buffer;
47 PacketBuffer d_response;
48 std::string d_path;
49 std::string d_scheme;
50 std::string d_host;
51 std::string d_queryString;
52 std::string d_sni;
53 std::string d_contentTypeOut;
54 std::unique_ptr<HeadersMap> d_headers;
55 size_t d_queryPos{0};
56 uint32_t d_statusCode{0};
57 Method d_method{Method::Unknown};
58 };
59
60 IncomingHTTP2Connection(ConnectionInfo&& connectionInfo, TCPClientThreadData& threadData, const struct timeval& now);
61 ~IncomingHTTP2Connection() = default;
62 void handleIO() override;
63 void handleResponse(const struct timeval& now, TCPResponse&& response) override;
64 void notifyIOError(const struct timeval& now, TCPResponse&& response) override;
65 bool active() const override;
66
67 private:
68 static ssize_t send_callback(nghttp2_session* session, const uint8_t* data, size_t length, int flags, void* user_data);
69 static int on_frame_recv_callback(nghttp2_session* session, const nghttp2_frame* frame, void* user_data);
70 static int on_data_chunk_recv_callback(nghttp2_session* session, uint8_t flags, StreamID stream_id, const uint8_t* data, size_t len, void* user_data);
71 static int on_stream_close_callback(nghttp2_session* session, StreamID stream_id, uint32_t error_code, void* user_data);
72 static int on_header_callback(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);
73 static int on_begin_headers_callback(nghttp2_session* session, const nghttp2_frame* frame, void* user_data);
74 static int on_error_callback(nghttp2_session* session, int lib_error_code, const char* msg, size_t len, void* user_data);
75 static void handleReadableIOCallback(int descriptor, FDMultiplexer::funcparam_t& param);
76 static void handleWritableIOCallback(int descriptor, FDMultiplexer::funcparam_t& param);
77
78 static constexpr size_t s_initialReceiveBufferSize{256U};
79
80 IOState sendResponse(const struct timeval& now, TCPResponse&& response) override;
81 bool forwardViaUDPFirst() const override
82 {
83 return true;
84 }
85 void restoreDOHUnit(std::unique_ptr<DOHUnitInterface>&&) override;
86 std::unique_ptr<DOHUnitInterface> getDOHUnit(uint32_t streamID) override;
87
88 void stopIO();
89 uint32_t getConcurrentStreamsCount() const;
90 void updateIO(IOState newState, const FDMultiplexer::callbackfunc_t& callback);
91 void handleIOError();
92 bool sendResponse(StreamID streamID, PendingQuery& context, uint16_t responseCode, const HeadersMap& customResponseHeaders, const std::string& contentType = "", bool addContentType = true);
93 void handleIncomingQuery(PendingQuery&& query, StreamID streamID);
94 bool checkALPN();
95 IOState readHTTPData();
96 void handleConnectionReady();
97 IOState handleHandshake(const struct timeval& now) override;
98 bool hasPendingWrite() const;
99 void writeToSocket(bool socketReady);
100 boost::optional<struct timeval> getIdleClientReadTTD(struct timeval now) const;
101
102 std::unique_ptr<nghttp2_session, decltype(&nghttp2_session_del)> d_session{nullptr, nghttp2_session_del};
103 std::unordered_map<StreamID, PendingQuery> d_currentStreams;
104 PacketBuffer d_out;
105 PacketBuffer d_in;
106 size_t d_outPos{0};
107 /* this connection is done, the remote end has closed the connection
108 or something like that. We do not want to try to write to it. */
109 bool d_connectionDied{false};
110 /* we are done reading from this connection, but we might still want to
111 write to it to close it properly */
112 bool d_connectionClosing{false};
113 /* Whether we are still waiting for more data to be buffered
114 before writing to the socket (false) or not. */
115 bool d_needFlush{false};
116 /* Whether we have data that we want to write to the socket,
117 but the socket is full. */
118 bool d_pendingWrite{false};
119 };
120
121 class NGHTTP2Headers
122 {
123 public:
124 enum class HeaderConstantIndexes
125 {
126 OK_200_VALUE = 0,
127 METHOD_NAME,
128 METHOD_VALUE,
129 SCHEME_NAME,
130 SCHEME_VALUE,
131 AUTHORITY_NAME,
132 X_FORWARDED_FOR_NAME,
133 PATH_NAME,
134 CONTENT_LENGTH_NAME,
135 STATUS_NAME,
136 LOCATION_NAME,
137 ACCEPT_NAME,
138 ACCEPT_VALUE,
139 CACHE_CONTROL_NAME,
140 CONTENT_TYPE_NAME,
141 CONTENT_TYPE_VALUE,
142 USER_AGENT_NAME,
143 USER_AGENT_VALUE,
144 X_FORWARDED_PORT_NAME,
145 X_FORWARDED_PROTO_NAME,
146 X_FORWARDED_PROTO_VALUE_DNS_OVER_UDP,
147 X_FORWARDED_PROTO_VALUE_DNS_OVER_TCP,
148 X_FORWARDED_PROTO_VALUE_DNS_OVER_TLS,
149 X_FORWARDED_PROTO_VALUE_DNS_OVER_HTTP,
150 X_FORWARDED_PROTO_VALUE_DNS_OVER_HTTPS,
151 COUNT
152 };
153
154 static void addStaticHeader(std::vector<nghttp2_nv>& headers, HeaderConstantIndexes nameKey, HeaderConstantIndexes valueKey);
155 static void addDynamicHeader(std::vector<nghttp2_nv>& headers, HeaderConstantIndexes nameKey, const std::string_view& value);
156 static void addCustomDynamicHeader(std::vector<nghttp2_nv>& headers, const std::string& name, const std::string_view& value);
157 };
158
159 #endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */