cutelyst  4.4.0
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  auto it = streams.constBegin();
80  while (it != streams.constEnd()) {
81  // If we deleteLater the context, there might
82  // be an event that tries to finalize the request
83  // and it will encounter a null context pointer
84  delete it.value()->context;
85  delete it.value();
86  ++it;
87  }
88  streams.clear();
89 
90  headersBuffer.clear();
91  maxStreamId = 0;
92  streamForContinuation = 0;
93  dataSent = 0;
94  windowSize = 65535;
95  settingsInitialWindowSize = 65535;
96  canPush = false;
97  }
98 
99  quint32 stream_id = 0;
100  quint32 pktsize = 0;
101 
102  QByteArray headersBuffer;
103  HPack *hpack = nullptr;
104  quint64 streamForContinuation = 0;
105  quint32 maxStreamId = 0;
106  qint32 dataSent = 0;
107  qint32 windowSize = 65535;
108  qint32 settingsInitialWindowSize = 65535;
109  quint32 settingsMaxFrameSize = 16384;
110  quint8 processing = 0;
111  bool canPush = true;
112 
114 };
115 
116 class ProtocolHttp2 final : public Protocol
117 {
118 public:
119  explicit ProtocolHttp2(Server *wsgi);
120  ~ProtocolHttp2() override;
121 
122  Type type() const override;
123 
124  void parse(Cutelyst::Socket *sock, QIODevice *io) const override final;
125 
126  ProtocolData *createData(Cutelyst::Socket *sock) const override final;
127 
128  int parseSettings(ProtoRequestHttp2 *request, QIODevice *io, const H2Frame &fr) const;
129  int parseData(ProtoRequestHttp2 *request, QIODevice *io, const H2Frame &fr) const;
130  int parseHeaders(ProtoRequestHttp2 *request, QIODevice *io, const H2Frame &fr) const;
131  int parsePriority(ProtoRequestHttp2 *request, QIODevice *io, const H2Frame &fr) const;
132  int parsePing(ProtoRequestHttp2 *request, QIODevice *io, const H2Frame &fr) const;
133  int parseRstStream(ProtoRequestHttp2 *request, QIODevice *io, const H2Frame &fr) const;
134  int parseWindowUpdate(ProtoRequestHttp2 *request, QIODevice *io, const H2Frame &fr) const;
135 
136  int sendGoAway(QIODevice *io, quint32 lastStreamId, quint32 error) const;
137  int sendRstStream(QIODevice *io, quint32 streamId, quint32 error) const;
138  int sendSettings(QIODevice *io, const std::vector<std::pair<quint16, quint32>> &settings) const;
139  int sendSettingsAck(QIODevice *io) const;
140  int sendPing(QIODevice *io, quint8 flags, const char *data = nullptr, qint32 dataLen = 0) const;
141  int sendData(QIODevice *io,
142  quint32 streamId,
143  qint32 flags,
144  const char *data,
145  qint32 dataLen) const;
146  int sendFrame(QIODevice *io,
147  quint8 type,
148  quint8 flags = 0,
149  quint32 streamId = 0,
150  const char *data = nullptr,
151  qint32 dataLen = 0) const;
152 
153  void queueStream(Cutelyst::Socket *socket, H2Stream *stream) const;
154 
155  bool
156  upgradeH2C(Cutelyst::Socket *socket, QIODevice *io, const Cutelyst::EngineRequest &request);
157 
158 public:
159  quint32 m_maxFrameSize;
160  qint32 m_headerTableSize;
161 };
162 
163 } // namespace Cutelyst
164 
165 #endif // PROTOCOLHTTP2_H
qint64 doWrite(const char *data, qint64 len) override final
void processingFinished() override final
bool writeHeaders(quint16 status, const Cutelyst::Headers &headers) override final
Container for HTTP headers.
Definition: headers.h:24
Implements a web server.
Definition: server.h:60
The Cutelyst namespace holds all public Cutelyst API.
void clear()