fastcgi++
A C++ FastCGI/Web API
protocol.hpp
Go to the documentation of this file.
1 
10 /*******************************************************************************
11 * Copyright (C) 2017 Eddie Carle [eddie@isatec.ca] *
12 * *
13 * This file is part of fastcgi++. *
14 * *
15 * fastcgi++ is free software: you can redistribute it and/or modify it under *
16 * the terms of the GNU Lesser General Public License as published by the Free *
17 * Software Foundation, either version 3 of the License, or (at your option) *
18 * any later version. *
19 * *
20 * fastcgi++ is distributed in the hope that it will be useful, but WITHOUT ANY *
21 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for *
23 * more details. *
24 * *
25 * You should have received a copy of the GNU Lesser General Public License *
26 * along with fastcgi++. If not, see <http://www.gnu.org/licenses/>. *
27 *******************************************************************************/
28 
29 #ifndef FASTCGIPP_PROTOCOL_HPP
30 #define FASTCGIPP_PROTOCOL_HPP
31 
32 #include <memory>
33 #include <cstdint>
34 #include <algorithm>
35 #include <map>
36 #include <vector>
37 
38 #include "fastcgi++/message.hpp"
39 #include "fastcgi++/sockets.hpp"
40 
42 namespace Fastcgipp
43 {
45  extern const char version[];
46 
48 
54  namespace Protocol
55  {
57  typedef uint16_t FcgiId;
58 
60  const uint16_t badFcgiId = 0xffffUL;
61 
63 
71  struct RequestId
72  {
74 
82  FcgiId id,
83  const Socket& socket):
84  m_socket(socket),
85  m_id(id)
86  {}
87 
88  RequestId(const RequestId& x):
89  m_socket(x.m_socket),
90  m_id(x.m_id)
91  {}
92 
94  m_socket(Socket()),
95  m_id(badFcgiId)
96  {}
97 
99  {
100  m_socket = x.m_socket;
101  m_id = x.m_id;
102  return *this;
103  }
104 
107 
109  FcgiId m_id;
110 
112  struct Less
113  {
114  using is_transparent = std::true_type;
115 
116  bool operator()(const RequestId& x, const RequestId& y) const
117  {
118  if(x.m_socket == y.m_socket)
119  return x.m_id < y.m_id;
120  else
121  return x.m_socket < y.m_socket;
122  }
123 
124  bool operator()(const RequestId& id, const Socket& socket) const
125  {
126  return id.m_socket < socket;
127  }
128 
129  bool operator()(const Socket& socket, const RequestId& id) const
130  {
131  return socket < id.m_socket;
132  }
133  };
134  };
135 
137  template<class T>
138  using Requests = std::map<RequestId, T, RequestId::Less>;
139 
141  enum class RecordType: uint8_t
142  {
143  BEGIN_REQUEST=1,
144  ABORT_REQUEST=2,
145  END_REQUEST=3,
146  PARAMS=4,
147  IN=5,
148  OUT=6,
149  ERR=7,
150  DATA=8,
151  GET_VALUES=9,
153  UNKNOWN_TYPE=11
154  };
155 
157  const int version=1;
158 
160  const int chunkSize=8;
161 
163  enum class Role: uint16_t
164  {
165  RESPONDER=1,
166  AUTHORIZER=2,
167  FILTER=3
168  };
169 
171  enum class ProtocolStatus: uint8_t
172  {
174  CANT_MPX_CONN=1,
175  OVERLOADED=2,
176  UNKNOWN_ROLE=3
177  };
178 
180  template<size_t Size> struct Unsigned;
181  template<> struct Unsigned<2>
182  {
183  typedef uint16_t Type;
184  };
185  template<> struct Unsigned<4>
186  {
187  typedef uint32_t Type;
188  };
189  template<> struct Unsigned<8>
190  {
191  typedef uint64_t Type;
192  };
193 
195 
205  template<typename T> class BigEndian
206  {
207  private:
208  static const size_t size = sizeof(T);
209  static_assert(size==2 || size==4 || size==8, "Fastcgipp::Protocol::"
210  "BigEndian can only work with types of size 2, 4 or 8.");
211 
213  typedef typename Unsigned<size>::Type BaseType;
214 
216  unsigned char m_data[size];
217 
219  void set(T x)
220  {
221  union
222  {
223  BaseType base;
224  T actual;
225  };
226  actual = x;
227  for(unsigned int i=0; i<size; ++i)
228  m_data[i] = static_cast<unsigned char>(
229  0xff & base>>8*(size-1-i));
230  }
231 
232  public:
234  {
235  set(x);
236  return *this;
237  }
238 
240  {
241  set(x);
242  }
243 
244  constexpr BigEndian()
245  {}
246 
247  operator T() const
248  {
249  return read(m_data);
250  }
251 
253 
260  static T read(const unsigned char* source)
261  {
262  union
263  {
264  BaseType base;
265  T actual;
266  };
267  base = 0;
268 
269  for(unsigned int i=0; i<size; ++i)
270  base |= static_cast<BaseType>(*(source+i))
271  << 8*(size-1-i);
272 
273  return actual;
274  }
275 
277  static T read(const char* source)
278  {
279  return read(reinterpret_cast<const unsigned char*>(source));
280  }
281  };
282 
284 
292  struct Header
293  {
295  uint8_t version;
296 
299 
302 
305 
307  uint8_t paddingLength;
308 
310  uint8_t reserved;
311  };
312 
314 
324  {
326  static const int keepConnBit = 1;
327 
329 
338  bool kill() const
339  {
340  return !(flags & keepConnBit);
341  }
342 
345 
347  uint8_t flags;
348 
350  uint8_t reserved[5];
351  };
352 
354 
363  struct UnknownType
364  {
367 
369  uint8_t reserved[7];
370  };
371 
373 
383  struct EndRequest
384  {
387 
390 
392  uint8_t reserved[3];
393  };
394 
396 
418  bool processParamHeader(
419  const char* data,
420  const char* const dataEnd,
421  const char*& name,
422  const char*& value,
423  const char*& end);
424 
426 
444  template<int NAMELENGTH, int VALUELENGTH> struct ManagementReply
445  {
446  private:
447  static const int paddingLength = (chunkSize-1)-(
448  sizeof(Header)
449  +2
450  +NAMELENGTH
451  +VALUELENGTH
452  -1)%chunkSize;
453 
456 
458  uint8_t nameLength;
459 
461  uint8_t valueLength;
462 
464  uint8_t name[NAMELENGTH];
465 
467  uint8_t value[VALUELENGTH];
468 
470  uint8_t padding[paddingLength];
471 
472  public:
474 
485  const char* name_,
486  const char* value_):
487  nameLength(NAMELENGTH),
488  valueLength(VALUELENGTH)
489  {
490  std::copy(name_, name_+NAMELENGTH, name);
491  std::copy(value_, value_+VALUELENGTH, value);
492  header.version = version;
494  header.fcgiId = 0;
495  header.contentLength = NAMELENGTH+VALUELENGTH;
496  header.paddingLength= paddingLength;
497  }
498  };
499 
502 
505 
508  }
509 }
510 
511 #endif
uint8_t nameLength
Length in bytes of name.
Definition: protocol.hpp:458
BigEndian< FcgiId > fcgiId
Request ID.
Definition: protocol.hpp:301
BigEndian< uint16_t > contentLength
Content length.
Definition: protocol.hpp:304
The body for FastCGI records of type RecordType::END_REQUEST.
Definition: protocol.hpp:383
bool operator()(const RequestId &id, const Socket &socket) const
Definition: protocol.hpp:124
Topmost namespace for the fastcgi++ library.
RecordType type
Unknown record type.
Definition: protocol.hpp:366
const char version[]
Defines the fastcgi++ version.
Definition: protocol.cpp:91
const ManagementReply< 13, 2 > maxReqsReply
The maximum allowed requests at a time.
RequestId(FcgiId id, const Socket &socket)
Construct from an FcgiId and a Socket.
Definition: protocol.hpp:81
bool processParamHeader(const char *data, const char *const dataEnd, const char *&name, const char *&value, const char *&end)
Process the body of a FastCGI record of type RecordType::PARAMS.
Definition: protocol.cpp:32
RequestId(const RequestId &x)
Definition: protocol.hpp:88
RecordType type
Record type.
Definition: protocol.hpp:298
Data structure used as the header for FastCGI records.
Definition: protocol.hpp:292
Unsigned< size >::Type BaseType
Underlying unsigned integral type.
Definition: protocol.hpp:210
const ManagementReply< 15, 1 > mpxsConnsReply
Where or not requests can be multiplexed over a single connections.
ProtocolStatus
Possible statuses a request may declare when complete.
Definition: protocol.hpp:171
BigEndian< Role > role
Role.
Definition: protocol.hpp:344
Header header
Management records header.
Definition: protocol.hpp:455
const uint16_t badFcgiId
Constant that defines a bad/special FcgiId.
Definition: protocol.hpp:60
The body for FastCGI records with a RecordType of UNKNOWN_TYPE.
Definition: protocol.hpp:363
Allows raw storage of types in big endian format.
Definition: protocol.hpp:205
Get unsigned integral type from size.
Definition: protocol.hpp:180
BigEndian & operator=(T x)
Definition: protocol.hpp:233
uint16_t FcgiId
The internal ID of a FastCGI request.
Definition: protocol.hpp:57
uint8_t valueLength
Length in bytes of value.
Definition: protocol.hpp:461
Class for representing an OS level I/O socket.
Definition: sockets.hpp:83
A unique identifier for each FastCGI request.
Definition: protocol.hpp:71
uint8_t version
FastCGI version number.
Definition: protocol.hpp:295
BigEndian< int32_t > appStatus
Return value.
Definition: protocol.hpp:386
const int chunkSize
All FastCGI records will be a multiple of this many bytes.
Definition: protocol.hpp:160
Defines the Message data structure.
We need this uglyness to find ranges based purely on the socket.
Definition: protocol.hpp:112
bool operator()(const Socket &socket, const RequestId &id) const
Definition: protocol.hpp:129
For the reply of FastCGI management records.
Definition: protocol.hpp:444
uint8_t reserved
Reseved for future use and header padding.
Definition: protocol.hpp:310
static T read(const char *source)
Simply casts char to unsigned char.
Definition: protocol.hpp:277
bool kill() const
Get keep alive value from the record body.
Definition: protocol.hpp:338
The body for FastCGI records with a RecordType of BEGIN_REQUEST.
Definition: protocol.hpp:323
RecordType
Defines the types of records within the FastCGI protocol.
Definition: protocol.hpp:141
Socket m_socket
Associated socket.
Definition: protocol.hpp:106
static T read(const unsigned char *source)
Static function for reading the value out of a data array.
Definition: protocol.hpp:260
ManagementReply(const char *name_, const char *value_)
Construct the record based on the name data and value data.
Definition: protocol.hpp:484
FcgiId m_id
Internal FastCGI request ID.
Definition: protocol.hpp:109
Declares everything for interfaces with OS level sockets.
uint8_t paddingLength
Length of record padding.
Definition: protocol.hpp:307
const ManagementReply< 14, 2 > maxConnsReply
The maximum allowed file descriptors open at a time.
RequestId & operator=(const RequestId &x)
Definition: protocol.hpp:98
const int version
The version of the FastCGI protocol that this adheres to.
Definition: protocol.hpp:157
std::map< RequestId, T, RequestId::Less > Requests
A simple associative container that indexes with RequestId.
Definition: protocol.hpp:138
bool operator()(const RequestId &x, const RequestId &y) const
Definition: protocol.hpp:116
Role
Defines the possible roles a FastCGI application may play.
Definition: protocol.hpp:163
ProtocolStatus protocolStatus
Requests Status.
Definition: protocol.hpp:389