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 <map>
00026 #include <string>
00027 #include <endian.h>
00028
00029 #include <boost/shared_array.hpp>
00030
00032 namespace Fastcgipp
00033 {
00035
00041 namespace Protocol
00042 {
00044 const int version=1;
00045
00047 const int chunkSize=8;
00048
00050 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 };
00051
00053 enum Role { RESPONDER=1, AUTHORIZER=2, FILTER=3 };
00054
00056 enum ProtocolStatus { REQUEST_COMPLETE=0, CANT_MPX_CONN=1, OVERLOADED=2, UNKNOWN_ROLE=3 };
00057
00059 typedef uint16_t RequestId;
00060
00062
00069 struct FullId
00070 {
00072
00079 FullId(RequestId fcgiId_, int fd_): fcgiId(fcgiId_), fd(fd_) { }
00080 FullId() { }
00082 RequestId fcgiId;
00084 uint16_t fd;
00085 };
00086
00088
00091 inline bool operator>(const FullId& x, const FullId& y) { return *(uint32_t*)&x.fcgiId > *(uint32_t*)&y.fcgiId; }
00092
00094
00097 inline bool operator<(const FullId& x, const FullId& y) { return *(uint32_t*)&x.fcgiId < *(uint32_t*)&y.fcgiId; }
00098
00100
00103 inline bool operator==(const FullId& x, const FullId& y) { return *(uint32_t*)&x.fcgiId == *(uint32_t*)&y.fcgiId; }
00104
00106
00114 #if __BYTE_ORDER == __LITTLE_ENDIAN
00115 template<class T> T readBigEndian(T value)
00116 {
00117 T result;
00118 char* pValue=(char*)&value-1;
00119 char* pValueEnd=pValue+sizeof(T);
00120 char* pResult=(char*)&result+sizeof(T);
00121 while(pValue!=pValueEnd)
00122 *--pResult=*++pValue;
00123 return result;
00124 }
00125 #elif __BYTE_ORDER == __BIG_ENDIAN
00126 template<class T> T readBigEndian(T value)
00127 {
00128 return value;
00129 }
00130 #endif
00131
00133
00138 class Header
00139 {
00140 public:
00142
00145 void setVersion(uint8_t version_) { version=version_; }
00146
00148
00151 int getVersion() const { return version; }
00152
00154
00157 void setType(RecordType type_) { type=static_cast<uint8_t>(type_); }
00158
00160
00163 RecordType getType() const { return static_cast<RecordType>(type); }
00164
00166
00169 void setRequestId(RequestId requestId_) { *(uint16_t*)&requestIdB1=readBigEndian(requestId_); }
00170
00172
00175 RequestId getRequestId() const { return readBigEndian(*(uint16_t*)&requestIdB1); }
00176
00178
00181 void setContentLength(uint16_t contentLength_) { *(uint16_t*)&contentLengthB1=readBigEndian(contentLength_); }
00182
00184
00187 int getContentLength() const { return readBigEndian(*(uint16_t*)&contentLengthB1); }
00188
00190
00193 void setPaddingLength(uint8_t paddingLength_) { paddingLength=paddingLength_; }
00194
00196
00199 int getPaddingLength() const { return paddingLength; }
00200 private:
00202 uint8_t version;
00204 uint8_t type;
00206 uint8_t requestIdB1;
00208 uint8_t requestIdB0;
00210 uint8_t contentLengthB1;
00212 uint8_t contentLengthB0;
00214 uint8_t paddingLength;
00216 uint8_t reserved;
00217 };
00218
00219
00221
00226 class BeginRequest
00227 {
00228 public:
00230
00233 Role getRole() const { return static_cast<Role>(readBigEndian(*(uint16_t*)&roleB1)); }
00234
00236
00243 bool getKeepConn() const { return flags & keepConnBit; }
00244 private:
00246 static const int keepConnBit = 1;
00247
00249 uint8_t roleB1;
00251 uint8_t roleB0;
00253 uint8_t flags;
00255 uint8_t reserved[5];
00256 };
00257
00259
00264 class UnknownType
00265 {
00266 public:
00268
00271 void setType(RecordType type_) { type=static_cast<uint8_t>(type_); }
00272 private:
00274 uint8_t type;
00276 uint8_t reserved[7];
00277 };
00278
00280
00286 class EndRequest
00287 {
00288 public:
00290
00296 void setAppStatus(int status) { *(int*)&appStatusB3=readBigEndian(status); }
00297
00299
00304 void setProtocolStatus(ProtocolStatus status) { protocolStatus=static_cast<uint8_t>(status); }
00305 private:
00307 uint8_t appStatusB3;
00309 uint8_t appStatusB2;
00311 uint8_t appStatusB1;
00313 uint8_t appStatusB0;
00315 uint8_t protocolStatus;
00317 uint8_t reserved[3];
00318 };
00319
00321
00331 void processParamHeader(const char* data, const char*& name, size_t& nameSize, const char*& value, size_t& valueSize);
00332
00333
00335
00348 template<int NAMELENGTH, int VALUELENGTH, int PADDINGLENGTH>
00349 struct ManagementReply
00350 {
00351 private:
00353 Header header;
00355 uint8_t nameLength;
00357 uint8_t valueLength;
00359 uint8_t name[NAMELENGTH];
00361 uint8_t value[VALUELENGTH];
00363 uint8_t padding[PADDINGLENGTH];
00364 public:
00366
00376 ManagementReply(const char* name_, const char* value_): nameLength(NAMELENGTH), valueLength(VALUELENGTH)
00377 {
00378 for(int i=0; i<NAMELENGTH; i++) name[i]=*(name_+i);
00379 for(int i=0; i<VALUELENGTH; i++) value[i]=*(value_+i);
00380 header.setVersion(version);
00381 header.setType(GET_VALUES_RESULT);
00382 header.setRequestId(0);
00383 header.setContentLength(NAMELENGTH+VALUELENGTH);
00384 header.setPaddingLength(PADDINGLENGTH);
00385 }
00386 };
00387
00389 extern ManagementReply<14, 2, 8> maxConnsReply;
00391 extern ManagementReply<13, 2, 1> maxReqsReply;
00393 extern ManagementReply<15, 1, 8> mpxsConnsReply;
00394 }
00395
00397
00406 struct Message
00407 {
00409 int type;
00411 size_t size;
00413 boost::shared_array<char> data;
00414 };
00415 }
00416
00417 #endif