cutelyst  5.0.1
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
protocolhttp2.h
1 /*
2  * SPDX-FileCopyrightText: (C) 2018 Daniel Nicoletti <dantti12@gmail.com>
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 #ifndef PROTOCOLHTTP2_H
6 #define PROTOCOLHTTP2_H
7 
8 #include "hpack.h"
9 #include "protocol.h"
10 #include "socket.h"
11 
12 #include <context.h>
13 #include <enginerequest.h>
14 
15 #include <QObject>
16 
17 // namespace Cutelyst {
18 // class Headers;
19 // }
20 
21 class QEventLoop;
22 namespace Cutelyst {
23 
24 class H2Frame
25 {
26 public:
27  quint32 len;
28  quint32 streamId;
29  quint8 type;
30  quint8 flags;
31 };
32 
33 class ProtoRequestHttp2;
34 class H2Stream final : public Cutelyst::EngineRequest
35 {
36 public:
37  enum State { Idle, Open, HalfClosed, Closed };
38  H2Stream(quint32 streamId, qint32 initialWindowSize, ProtoRequestHttp2 *protoRequestH2);
39  ~H2Stream() override;
40 
41  qint64 doWrite(const char *data, qint64 len) override final;
42 
43  bool writeHeaders(quint16 status, const Cutelyst::Headers &headers) override final;
44 
45  void processingFinished() override final;
46 
47  void windowUpdated();
48 
49  QEventLoop *loop = nullptr;
50  QByteArray scheme;
51  ProtoRequestHttp2 *protoRequest;
52  quint32 streamId;
53  qint32 windowSize = 65535;
54  qint64 contentLength = -1;
55  qint32 dataSent = 0;
56  qint64 consumedData = 0;
57  quint8 state = Idle;
58  bool gotPath = false;
59 };
60 
61 class ProtoRequestHttp2 final : public ProtocolData
62 {
63  Q_GADGET
64 public:
65  ProtoRequestHttp2(Cutelyst::Socket *sock, int bufferSize);
66  ~ProtoRequestHttp2() override;
67 
68  void setupNewConnection(Cutelyst::Socket *sock) override final;
69 
70  inline void resetData() override final
71  {
72  ProtocolData::resetData();
73 
74  stream_id = 0;
75  pktsize = 0;
76  delete hpack;
77  hpack = nullptr;
78 
79  for (const auto &stream : std::as_const(streams)) {
80  // If we deleteLater the context, there might
81  // be an event that tries to finalize the request
82  // and it will encounter a null context pointer
83  delete stream->context;
84  delete stream;
85  }
86 
87  streams.clear();
88 
89  headersBuffer.clear();
90  maxStreamId = 0;
91  streamForContinuation = 0;
92  dataSent = 0;
93  windowSize = 65535;
94  settingsInitialWindowSize = 65535;
95  canPush = false;
96  }
97 
98  quint32 stream_id = 0;
99  quint32 pktsize = 0;
100 
101  QByteArray headersBuffer;
102  HPack *hpack = nullptr;
103  quint64 streamForContinuation = 0;
104  quint32 maxStreamId = 0;
105  qint32 dataSent = 0;
106  qint32 windowSize = 65535;
107  qint32 settingsInitialWindowSize = 65535;
108  quint32 settingsMaxFrameSize = 16384;
109  quint8 processing = 0;
110  bool canPush = true;
111 
113 };
114 
115 class ProtocolHttp2 final : public Protocol
116 {
117 public:
118  explicit ProtocolHttp2(Server *server);
119  ~ProtocolHttp2() override;
120 
121  Type type() const override;
122 
123  void parse(Cutelyst::Socket *sock, QIODevice *io) const override final;
124 
125  ProtocolData *createData(Cutelyst::Socket *sock) const override final;
126 
127  int parseSettings(ProtoRequestHttp2 *request, QIODevice *io, const H2Frame &fr) const;
128  int parseData(ProtoRequestHttp2 *request, QIODevice *io, const H2Frame &fr) const;
129  int parseHeaders(ProtoRequestHttp2 *request, QIODevice *io, const H2Frame &fr) const;
130  int parsePriority(const ProtoRequestHttp2 *request, QIODevice *io, const H2Frame &fr) const;
131  int parsePing(const ProtoRequestHttp2 *request, QIODevice *io, const H2Frame &fr) const;
132  int parseRstStream(ProtoRequestHttp2 *request, QIODevice *io, const H2Frame &fr) const;
133  int parseWindowUpdate(ProtoRequestHttp2 *request, QIODevice *io, const H2Frame &fr) const;
134 
135  int sendGoAway(QIODevice *io, quint32 lastStreamId, quint32 error) const;
136  int sendRstStream(QIODevice *io, quint32 streamId, quint32 error) const;
137  int sendSettings(QIODevice *io, const std::vector<std::pair<quint16, quint32>> &settings) const;
138  int sendSettingsAck(QIODevice *io) const;
139  int sendPing(QIODevice *io, quint8 flags, const char *data = nullptr, qint32 dataLen = 0) const;
140  int sendData(QIODevice *io,
141  quint32 streamId,
142  qint32 flags,
143  const char *data,
144  qint32 dataLen) const;
145  int sendFrame(QIODevice *io,
146  quint8 type,
147  quint8 flags = 0,
148  quint32 streamId = 0,
149  const char *data = nullptr,
150  qint32 dataLen = 0) const;
151 
152  void queueStream(Cutelyst::Socket *socket, H2Stream *stream) const;
153 
154  bool
155  upgradeH2C(Cutelyst::Socket *socket, QIODevice *io, const Cutelyst::EngineRequest &request);
156 
157 public:
158  quint32 m_maxFrameSize;
159  qint32 m_headerTableSize;
160 };
161 
162 } // namespace Cutelyst
163 
164 #endif // PROTOCOLHTTP2_H
void clear()
bool writeHeaders(quint16 status, const Cutelyst::Headers &headers) override final
Container for HTTP headers.
Definition: headers.h:23
Implements a web server.
Definition: server.h:59
void processingFinished() override final
The Cutelyst namespace holds all public Cutelyst API.
qint64 doWrite(const char *data, qint64 len) override final