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 #include <stdint.h>
00029
00030 #include <boost/shared_array.hpp>
00031
00033 namespace Fastcgipp
00034 {
00035 namespace Protocol
00036 {
00038 typedef uint16_t RequestId;
00039
00041
00048 struct FullId
00049 {
00051
00058 FullId(RequestId fcgiId_, int fd_): fcgiId(fcgiId_), fd(fd_) { }
00059 FullId() { }
00061 RequestId fcgiId;
00063 uint16_t fd;
00064 };
00065
00067 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 };
00068
00070 extern char* recordTypeLabels[];
00071 }
00072 }
00073
00074
00075 #include <fastcgi++/exceptions.hpp>
00076
00078 namespace Fastcgipp
00079 {
00081
00087 namespace Protocol
00088 {
00090 const int version=1;
00091
00093 const int chunkSize=8;
00094
00096 enum Role { RESPONDER=1, AUTHORIZER=2, FILTER=3 };
00097
00099 enum ProtocolStatus { REQUEST_COMPLETE=0, CANT_MPX_CONN=1, OVERLOADED=2, UNKNOWN_ROLE=3 };
00100
00102
00105 inline bool operator>(const FullId& x, const FullId& y) { return *(uint32_t*)&x.fcgiId > *(uint32_t*)&y.fcgiId; }
00106
00108
00111 inline bool operator<(const FullId& x, const FullId& y) { return *(uint32_t*)&x.fcgiId < *(uint32_t*)&y.fcgiId; }
00112
00114
00117 inline bool operator==(const FullId& x, const FullId& y) { return *(uint32_t*)&x.fcgiId == *(uint32_t*)&y.fcgiId; }
00118
00120
00128 #if __BYTE_ORDER == __LITTLE_ENDIAN
00129 template<class T> T readBigEndian(T value)
00130 {
00131 T result;
00132 char* pValue=(char*)&value-1;
00133 char* pValueEnd=pValue+sizeof(T);
00134 char* pResult=(char*)&result+sizeof(T);
00135 while(pValue!=pValueEnd)
00136 *--pResult=*++pValue;
00137 return result;
00138 }
00139 #elif __BYTE_ORDER == __BIG_ENDIAN
00140 template<class T> T readBigEndian(T value)
00141 {
00142 return value;
00143 }
00144 #endif
00145
00147
00152 class Header
00153 {
00154 public:
00156
00159 void setVersion(uint8_t version_) { version=version_; }
00160
00162
00165 int getVersion() const { return version; }
00166
00168
00171 void setType(RecordType type_) { type=static_cast<uint8_t>(type_); }
00172
00174
00177 RecordType getType() const { return static_cast<RecordType>(type); }
00178
00180
00183 void setRequestId(RequestId requestId_) { *(uint16_t*)&requestIdB1=readBigEndian(requestId_); }
00184
00186
00189 RequestId getRequestId() const { return readBigEndian(*(uint16_t*)&requestIdB1); }
00190
00192
00195 void setContentLength(uint16_t contentLength_) { *(uint16_t*)&contentLengthB1=readBigEndian(contentLength_); }
00196
00198
00201 int getContentLength() const { return readBigEndian(*(uint16_t*)&contentLengthB1); }
00202
00204
00207 void setPaddingLength(uint8_t paddingLength_) { paddingLength=paddingLength_; }
00208
00210
00213 int getPaddingLength() const { return paddingLength; }
00214 private:
00216 uint8_t version;
00218 uint8_t type;
00220 uint8_t requestIdB1;
00222 uint8_t requestIdB0;
00224 uint8_t contentLengthB1;
00226 uint8_t contentLengthB0;
00228 uint8_t paddingLength;
00230 uint8_t reserved;
00231 };
00232
00233
00235
00240 class BeginRequest
00241 {
00242 public:
00244
00247 Role getRole() const { return static_cast<Role>(readBigEndian(*(uint16_t*)&roleB1)); }
00248
00250
00257 bool getKeepConn() const { return flags & keepConnBit; }
00258 private:
00260 static const int keepConnBit = 1;
00261
00263 uint8_t roleB1;
00265 uint8_t roleB0;
00267 uint8_t flags;
00269 uint8_t reserved[5];
00270 };
00271
00273
00278 class UnknownType
00279 {
00280 public:
00282
00285 void setType(RecordType type_) { type=static_cast<uint8_t>(type_); }
00286 private:
00288 uint8_t type;
00290 uint8_t reserved[7];
00291 };
00292
00294
00300 class EndRequest
00301 {
00302 public:
00304
00310 void setAppStatus(int status) { *(int*)&appStatusB3=readBigEndian(status); }
00311
00313
00318 void setProtocolStatus(ProtocolStatus status) { protocolStatus=static_cast<uint8_t>(status); }
00319 private:
00321 uint8_t appStatusB3;
00323 uint8_t appStatusB2;
00325 uint8_t appStatusB1;
00327 uint8_t appStatusB0;
00329 uint8_t protocolStatus;
00331 uint8_t reserved[3];
00332 };
00333
00335
00345 bool processParamHeader(const char* data, size_t dataSize, const char*& name, size_t& nameSize, const char*& value, size_t& valueSize);
00346
00347
00349
00362 template<int NAMELENGTH, int VALUELENGTH, int PADDINGLENGTH>
00363 struct ManagementReply
00364 {
00365 private:
00367 Header header;
00369 uint8_t nameLength;
00371 uint8_t valueLength;
00373 uint8_t name[NAMELENGTH];
00375 uint8_t value[VALUELENGTH];
00377 uint8_t padding[PADDINGLENGTH];
00378 public:
00380
00390 ManagementReply(const char* name_, const char* value_): nameLength(NAMELENGTH), valueLength(VALUELENGTH)
00391 {
00392 for(int i=0; i<NAMELENGTH; i++) name[i]=*(name_+i);
00393 for(int i=0; i<VALUELENGTH; i++) value[i]=*(value_+i);
00394 header.setVersion(version);
00395 header.setType(GET_VALUES_RESULT);
00396 header.setRequestId(0);
00397 header.setContentLength(NAMELENGTH+VALUELENGTH);
00398 header.setPaddingLength(PADDINGLENGTH);
00399 }
00400 };
00401
00403 extern ManagementReply<14, 2, 8> maxConnsReply;
00405 extern ManagementReply<13, 2, 1> maxReqsReply;
00407 extern ManagementReply<15, 1, 8> mpxsConnsReply;
00408 }
00409
00411
00420 struct Message
00421 {
00423 int type;
00425 size_t size;
00427 boost::shared_array<char> data;
00428 };
00429 }
00430
00431 #endif