1 /*
2  * Copyright (C) 2016-2018 Daniel Nicoletti <dantti12@gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 #ifndef PROTOCOL_H
19 #define PROTOCOL_H
20 
21 #include <QObject>
22 #include <QDebug>
23 
24 class QIODevice;
25 
26 namespace Cutelyst {
27 
28 class Server;
29 class Socket;
30 class Protocol;
31 class ProtocolData
32 {
33     Q_GADGET
34 public:
35     ProtocolData(Socket *sock, int bufferSize);
36     virtual ~ProtocolData();
37 
38     enum HeaderConnection {
39         HeaderConnectionNotSet = 0,
40         HeaderConnectionKeep,
41         HeaderConnectionClose,
42         HeaderConnectionUpgrade
43     };
44     Q_ENUM(HeaderConnection)
45 
46     enum ParserState {
47         MethodLine = 0,
48         HeaderLine,
49         ContentBody,
50         H2Frames
51     };
Q_ENUM(ParserState)52     Q_ENUM(ParserState)
53 
54     inline virtual void resetData() {
55         connState = MethodLine;
56         buf_size = 0;
57         headerConnection = HeaderConnectionNotSet;
58         headerHost = false;
59         X_Forwarded_For = false;
60         X_Forwarded_Host = false;
61         X_Forwarded_Proto = false;
62     }
63 
socketDisconnected()64     virtual void socketDisconnected() {}
65     virtual void setupNewConnection(Socket *sock) = 0;
66 
67     qint64 contentLength = 0;
68     Socket *sock;//temporary
69     QIODevice *io;
70     ProtocolData *upgradedFrom = nullptr;
71     int buf_size = 0;
72     ParserState connState = MethodLine;
73     HeaderConnection headerConnection = HeaderConnectionNotSet;
74     char *buffer;
75     bool headerHost = false;
76     bool X_Forwarded_For = false;
77     bool X_Forwarded_Host = false;
78     bool X_Forwarded_Proto = false;
79 };
80 
81 class Protocol
82 {
83     Q_GADGET
84 public:
85     enum Type {
86         Unknown,
87         Http11,
88         Http2,
89         FastCGI1
90     };
91     Q_ENUM(Type)
92 
93     Protocol(Server *wsgi);
94     virtual ~Protocol();
95 
96     virtual Type type() const;
97 
98     virtual void parse(Socket *sock, QIODevice *io) const = 0;
99 
100     virtual ProtocolData *createData(Socket *sock) const = 0;
101 
102     QIODevice *createBody(qint64 contentLength) const;
103 
104     qint64 m_postBufferSize;
105     qint64 m_postBuffering;
106     int m_bufferSize;
107     char *m_postBuffer;
108 };
109 
net_be64(const char * buf)110 inline quint64 net_be64(const char *buf) {
111     quint64 ret = 0;
112     auto src = reinterpret_cast<const quint64 *>(buf);
113     auto ptr = reinterpret_cast<quint8 *>(&ret);
114     ptr[0] = static_cast<quint8>((*src >> 56) & 0xff);
115     ptr[1] = static_cast<quint8>((*src >> 48) & 0xff);
116     ptr[2] = static_cast<quint8>((*src >> 40) & 0xff);
117     ptr[3] = static_cast<quint8>((*src >> 32) & 0xff);
118     ptr[4] = static_cast<quint8>((*src >> 24) & 0xff);
119     ptr[5] = static_cast<quint8>((*src >> 16) & 0xff);
120     ptr[6] = static_cast<quint8>((*src >> 8) & 0xff);
121     ptr[7] = static_cast<quint8>(*src & 0xff);
122     return ret;
123 }
124 
net_be32(const char * buf)125 inline quint32 net_be32(const char *buf) {
126     quint32 ret = 0;
127     auto src = reinterpret_cast<const quint32 *>(buf);
128     auto ptr = reinterpret_cast<quint8 *>(&ret);
129     ptr[0] = static_cast<quint8>((*src >> 24) & 0xff);
130     ptr[1] = static_cast<quint8>((*src >> 16) & 0xff);
131     ptr[2] = static_cast<quint8>((*src >> 8) & 0xff);
132     ptr[3] = static_cast<quint8>(*src & 0xff);
133     return ret;
134 }
135 
net_be24(const char * buf)136 inline quint32 net_be24(const char *buf) {
137     quint32 ret = 0;
138     auto src = reinterpret_cast<const quint32 *>(buf);
139     auto ptr = reinterpret_cast<quint8 *>(&ret);
140     ptr[0] = static_cast<quint8>((*src >> 16) & 0xff);
141     ptr[1] = static_cast<quint8>((*src >> 8) & 0xff);
142     ptr[2] = static_cast<quint8>(*src & 0xff);
143     return ret;
144 }
145 
net_be16(const char * buf)146 inline quint16 net_be16(const char *buf) {
147     quint16 ret = 0;
148     auto src = reinterpret_cast<const quint16 *>(buf);
149     auto ptr = reinterpret_cast<quint8 *>(&ret);
150     ptr[0] = static_cast<quint8>((*src >> 8) & 0xff);
151     ptr[1] = static_cast<quint8>(*src & 0xff);
152     return ret;
153 }
154 
155 }
156 
157 #endif // PROTOCOL_H
158