libhttppp ..
Loading...
Searching...
No Matches
httpd.h
1/*******************************************************************************
2 * Copyright (c) 2014, Jan Koester jan.koester@gmx.net
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the <organization> nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *******************************************************************************/
27
28#include <netplus/socket.h>
29#include <netplus/eventapi.h>
30#include <netplus/threadpool.h>
31#include <atomic>
32#include <cstdint>
33#include <map>
34#include <memory>
35#include <mutex>
36#include <set>
37#include <string>
38#include <vector>
39
40#include "http.h"
41#include "qpack.h"
42#include "exception.h"
43
44#pragma once
45
46namespace cmdplus {
47 class CmdController;
48}
49
50namespace libhttppp {
51 class HttpEvent : public netplus::event {
52 public:
53 // h2OffloadThreads: when non-zero, spins up a background thread pool
54 // (see shouldOffloadH2Dispatch) that lets HTTP/2 streams whose
55 // RequestEvent does slow, blocking work (e.g. a backend network
56 // round-trip) run without blocking every other stream multiplexed
57 // on the same connection. Zero (the default) preserves the original
58 // fully-synchronous H2 dispatch behavior for every existing caller.
59 HttpEvent(std::vector<netplus::socket*> serversocket,int timeout = 1000,
60 size_t h2OffloadThreads = 0);
61
62 // Return true to have this stream's RequestEvent run on the H2
63 // offload thread pool instead of inline in the frame-processing
64 // loop. Called right after the per-stream request's headers have
65 // been parsed (so :path/:method are already available), before
66 // RequestEvent runs. Defaults to false — every route stays on the
67 // original synchronous path unless a subclass opts a specific
68 // route in. Has no effect if h2OffloadThreads is 0.
69 virtual bool shouldOffloadH2Dispatch(HttpRequest &tempreq, uint32_t streamId) const {
70 return false;
71 }
72
73 virtual void RequestEvent(HttpRequest &curreq,const int tid,ULONG_PTR args);
74 virtual void ResponseEvent(HttpRequest &curreq,const int tid,ULONG_PTR args);
75 virtual void ConnectEvent(HttpRequest &curreq,const int tid,ULONG_PTR args);
76 virtual void DisconnectEvent(HttpRequest &curreq,const int tid,ULONG_PTR args);
77
78 virtual bool Http2RequestEvent(netplus::con &curcon,
79 const int tid,
80 ULONG_PTR args,
81 const std::string &alpn,
82 const netplus::ssl::FramingCallback &frame_cb);
83 virtual void Http3StreamEvent(netplus::socket *sock,
84 uint64_t stream_id,
85 const std::vector<uint8_t> &data,
86 bool fin);
87
88 // Streaming body callbacks for H2/H3.
89 // Called when headers are complete for a body-bearing stream.
90 // Return true to handle body data via onH2DataChunk/onH3DataChunk
91 // instead of buffering the full body.
92 virtual bool onH2StreamHeaders(HttpRequest &conn, uint32_t streamId,
93 const std::vector<hpack::HeaderField> &headers);
94 virtual bool onH3StreamHeaders(netplus::socket *sock, uint64_t streamId,
95 const std::vector<qpack::HeaderField> &headers);
96
97 // Called for each body data chunk when streaming is enabled.
98 // endStream/fin: true on the last chunk.
99 virtual void onH2DataChunk(HttpRequest &conn, uint32_t streamId,
100 const char *data, size_t len, bool endStream,
101 std::string &h2out, const int tid, ULONG_PTR args);
102 virtual void onH3DataChunk(netplus::socket *sock, uint64_t streamId,
103 const char *data, size_t len, bool fin);
104
105 protected:
106 // Helpers for sending a complete response on an H2/H3 stream.
107 void sendH2StreamResponse(std::string &h2out, uint32_t streamId,
108 uint16_t status, const std::string &contentType,
109 const std::string &body);
110 void sendH3StreamResponse(netplus::socket *sock, uint64_t streamId,
111 uint16_t status, const std::string &contentType,
112 const std::string &body);
113 virtual void CreateConnection(std::shared_ptr<netplus::con> &res);
114
115 virtual void RequestEvent(netplus::con &curcon, const int tid, ULONG_PTR args);
116 virtual void ResponseEvent(netplus::con &curcon,const int tid,ULONG_PTR args);
117 virtual void ConnectEvent(netplus::con &curcon,const int tid,ULONG_PTR args);
118 virtual void DisconnectEvent(netplus::con &curcon,const int tid,ULONG_PTR args);
119
120 std::string _altSvcH3; // Alt-Svc value for HTTP/3 advertisement
121
122 // TLS session cache — shared across all accepted SSL connections
123 // to enable abbreviated TLS 1.2 handshakes on client reconnection.
124 netplus::TlsSessionCache _tlsSessionCache;
125 private:
126 // Per-stream state for HTTP/3: accumulates data and supports
127 // incremental H3 frame parsing for streaming body callbacks.
128 struct H3StreamState {
129 std::vector<uint8_t> data;
130 bool headersParsed = false;
131 bool streaming = false;
132 size_t parseOffset = 0;
133 };
134 std::mutex _h3BufferMutex;
135 std::map<uint64_t, H3StreamState> _h3StreamStates;
136 std::atomic<int> _h3NextTid{0};
137
138 // Non-null only when h2OffloadThreads > 0 was passed to the
139 // constructor. See shouldOffloadH2Dispatch / _dispatchH2Stream.
140 std::unique_ptr<netplus::ThreadPool> _h2DispatchPool;
141
142 // Returns true if the stream was handed off to the background
143 // offload pool instead of being finished synchronously — callers
144 // must treat that as "progress" for reprocess-loop purposes even
145 // though it leaves `out` unchanged, since the frame was still
146 // consumed from RecvData either way.
147 bool _dispatchH2Stream(HttpRequest &cureq, std::string &out,
148 uint32_t sid,
149 const std::vector<hpack::HeaderField> &decoded,
150 const std::string &reqBody,
151 const int tid, ULONG_PTR args);
152 // The part of stream dispatch that must run on the connection's
153 // owning thread: extracts the plugin's :res-* response headers off
154 // an already-completed tempreq, HPACK-encodes them, and frames the
155 // response (or sets up activeStreams for a streaming response).
156 // Shared by both the synchronous path and the offload-completion
157 // path so they behave identically once RequestEvent has returned.
158 void _finishH2Dispatch(HttpRequest &cureq, std::string &out,
159 uint32_t sid,
160 std::unique_ptr<HttpRequest> tempreq,
161 const int tid, ULONG_PTR args);
162 // Factored out of the synchronous dispatch loop's immediate-flush
163 // step so the offload-completion path (which has no "loop" to fall
164 // through to) can reuse the exact same send behavior.
165 bool _flushSendDataNow(HttpRequest &cureq);
166 void _resumeH2Streams(HttpRequest &cureq, std::string &out,
167 const int tid, ULONG_PTR args);
168 void _reapStalledH2Streams(HttpRequest &cureq, std::string &out);
169 };
170
171 class HttpD {
172 public:
173 HttpD(int argc, char** argv);
174 HttpD(const std::string &httpaddr, int port, int maxconnections, const std::string &sslcertpath, const std::string &sslkeypath, const std::string &sslpassword = "");
175 ~HttpD();
176 std::vector<netplus::socket*> getServerSockets();
177
178 // Reload SSL certificates from file(s). Updates all ssl/quic server sockets.
179 bool reloadCertificates(const std::string &certpath, const std::string &keypath, const std::string &password = "");
180 protected:
181 void FileServer();
182 private:
183
184 bool _fileServer;
185 std::vector<std::unique_ptr<netplus::socket>> _ServerSockets;
186 std::map<std::string, netplus::ssl::CertificateBundle> _certBundle;
187 HTTPException _httpexception;
188 };
189};
Definition exception.h:43
Definition httpd.h:171
Definition httpd.h:51
Definition http.h:366