fastcgi++
|
00001 00002 /*************************************************************************** 00003 * Copyright (C) 2007 Eddie Carle [eddie@erctech.org] * 00004 * * 00005 * This file is part of fastcgi++. * 00006 * * 00007 * fastcgi++ is free software: you can redistribute it and/or modify it * 00008 * under the terms of the GNU Lesser General Public License as published * 00009 * by the Free Software Foundation, either version 3 of the License, or (at * 00010 * your option) any later version. * 00011 * * 00012 * fastcgi++ is distributed in the hope that it will be useful, but WITHOUT * 00013 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * 00014 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * 00015 * License for more details. * 00016 * * 00017 * You should have received a copy of the GNU Lesser General Public License * 00018 * along with fastcgi++. If not, see <http://www.gnu.org/licenses/>. * 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