Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef PROTOCOL_HPP
00023 #define PROTOCOL_HPP
00024
00025 #include <fastcgi++/config.h>
00026 #include <map>
00027 #include <string>
00028 #include <exception>
00029
00030 #if defined (HAVE_ENDIAN_H)
00031 #include <endian.h>
00032 #elif defined (HAVE_MACHINE_ENDIAN_H)
00033 #include <machine/endian.h>
00034 #elif defined (HAVE_ARPA_ENDIAN_H)
00035 #include <arpa/nameser_compat.h>
00036 #else
00037 #error Could not locate a file that defines endianess
00038 #endif
00039
00040 #include <stdint.h>
00041
00042 #include <boost/shared_array.hpp>
00043
00044 #include <fastcgi++/message.hpp>
00045
00047 namespace Fastcgipp
00048 {
00050 extern const char version[];
00051 namespace Protocol
00052 {
00054 typedef uint16_t RequestId;
00055
00057
00064 struct FullId
00065 {
00067
00074 FullId(RequestId fcgiId_, int fd_): fcgiId(fcgiId_), fd(fd_) { }
00075 FullId() { }
00077 RequestId fcgiId;
00079 uint16_t fd;
00080 };
00081
00083 enum RecordType { BEGIN_REQUEST=1, ABORT_REQUEST=2, END_REQUEST=3, PARAMS=4, IN=5, OUT=6, ERR=7, DATA=8, GET_VALUES=9, GET_VALUES_RESULT=10, UNKNOWN_TYPE=11 };
00084
00086 extern const char* recordTypeLabels[];
00087 }
00088 }
00089
00090
00091 #include <fastcgi++/exceptions.hpp>
00092
00094 namespace Fastcgipp
00095 {
00097
00103 namespace Protocol
00104 {
00106 const int version=1;
00107
00109 const int chunkSize=8;
00110
00112 enum Role { RESPONDER=1, AUTHORIZER=2, FILTER=3 };
00113
00115 enum ProtocolStatus { REQUEST_COMPLETE=0, CANT_MPX_CONN=1, OVERLOADED=2, UNKNOWN_ROLE=3 };
00116
00118
00121 inline bool operator>(const FullId& x, const FullId& y) { return *(uint32_t*)&x.fcgiId > *(uint32_t*)&y.fcgiId; }
00122
00124
00127 inline bool operator<(const FullId& x, const FullId& y) { return *(uint32_t*)&x.fcgiId < *(uint32_t*)&y.fcgiId; }
00128
00130
00133 inline bool operator==(const FullId& x, const FullId& y) { return *(uint32_t*)&x.fcgiId == *(uint32_t*)&y.fcgiId; }
00134
00136
00144 #if __BYTE_ORDER == __LITTLE_ENDIAN
00145 template<class T> T readBigEndian(T value)
00146 {
00147 T result;
00148 char* pValue=(char*)&value-1;
00149 char* pValueEnd=pValue+sizeof(T);
00150 char* pResult=(char*)&result+sizeof(T);
00151 while(pValue!=pValueEnd)
00152 *--pResult=*++pValue;
00153 return result;
00154 }
00155 #elif __BYTE_ORDER == __BIG_ENDIAN
00156 template<class T> T readBigEndian(T value)
00157 {
00158 return value;
00159 }
00160 #endif
00161
00163
00168 class Header
00169 {
00170 public:
00172
00175 void setVersion(uint8_t version_) { version=version_; }
00176
00178
00181 int getVersion() const { return version; }
00182
00184
00187 void setType(RecordType type_) { type=static_cast<uint8_t>(type_); }
00188
00190
00193 RecordType getType() const { return static_cast<RecordType>(type); }
00194
00196
00199 void setRequestId(RequestId requestId_) { *(uint16_t*)&requestIdB1=readBigEndian(requestId_); }
00200
00202
00205 RequestId getRequestId() const { return readBigEndian(*(uint16_t*)&requestIdB1); }
00206
00208
00211 void setContentLength(uint16_t contentLength_) { *(uint16_t*)&contentLengthB1=readBigEndian(contentLength_); }
00212
00214
00217 int getContentLength() const { return readBigEndian(*(uint16_t*)&contentLengthB1); }
00218
00220
00223 void setPaddingLength(uint8_t paddingLength_) { paddingLength=paddingLength_; }
00224
00226
00229 int getPaddingLength() const { return paddingLength; }
00230 private:
00232 uint8_t version;
00234 uint8_t type;
00236 uint8_t requestIdB1;
00238 uint8_t requestIdB0;
00240 uint8_t contentLengthB1;
00242 uint8_t contentLengthB0;
00244 uint8_t paddingLength;
00246 uint8_t reserved;
00247 };
00248
00249
00251
00256 class BeginRequest
00257 {
00258 public:
00260
00263 Role getRole() const { return static_cast<Role>(readBigEndian(*(uint16_t*)&roleB1)); }
00264
00266
00273 bool getKeepConn() const { return flags & keepConnBit; }
00274 private:
00276 static const int keepConnBit = 1;
00277
00279 uint8_t roleB1;
00281 uint8_t roleB0;
00283 uint8_t flags;
00285 uint8_t reserved[5];
00286 };
00287
00289
00294 class UnknownType
00295 {
00296 public:
00298
00301 void setType(RecordType type_) { type=static_cast<uint8_t>(type_); }
00302 private:
00304 uint8_t type;
00306 uint8_t reserved[7];
00307 };
00308
00310
00316 class EndRequest
00317 {
00318 public:
00320
00326 void setAppStatus(int status) { *(int*)&appStatusB3=readBigEndian(status); }
00327
00329
00334 void setProtocolStatus(ProtocolStatus status) { protocolStatus=static_cast<uint8_t>(status); }
00335 private:
00337 uint8_t appStatusB3;
00339 uint8_t appStatusB2;
00341 uint8_t appStatusB1;
00343 uint8_t appStatusB0;
00345 uint8_t protocolStatus;
00347 uint8_t reserved[3];
00348 };
00349
00351
00362 void processParamHeader(const char* data, size_t dataSize, const char*& name, size_t& nameSize, const char*& value, size_t& valueSize);
00363
00364
00366
00379 template<int NAMELENGTH, int VALUELENGTH, int PADDINGLENGTH> struct ManagementReply
00380 {
00381 private:
00383 Header header;
00385 uint8_t nameLength;
00387 uint8_t valueLength;
00389 uint8_t name[NAMELENGTH];
00391 uint8_t value[VALUELENGTH];
00393 uint8_t padding[PADDINGLENGTH];
00394 public:
00396
00406 ManagementReply(const char* name_, const char* value_): nameLength(NAMELENGTH), valueLength(VALUELENGTH)
00407 {
00408 for(int i=0; i<NAMELENGTH; i++) name[i]=*(name_+i);
00409 for(int i=0; i<VALUELENGTH; i++) value[i]=*(value_+i);
00410 header.setVersion(version);
00411 header.setType(GET_VALUES_RESULT);
00412 header.setRequestId(0);
00413 header.setContentLength(NAMELENGTH+VALUELENGTH);
00414 header.setPaddingLength(PADDINGLENGTH);
00415 }
00416 };
00417
00419 extern ManagementReply<14, 2, 8> maxConnsReply;
00421 extern ManagementReply<13, 2, 1> maxReqsReply;
00423 extern ManagementReply<15, 1, 8> mpxsConnsReply;
00424 }
00425 }
00426
00427 #endif