+#ifndef __FCGI_REQUEST_H__
+#define __FCGI_REQUEST_H__
+
+namespace aeb {
+namespace fcgi {
+
+ //! Fastcgi Id
+ typedef uint16_t Id;
+
+ enum class RecordType : uint8_t
+ {
+ BEGIN_REQ = 1
+ ,ABORT_REQ = 2
+ ,END_REQ = 3
+ ,PARAMS = 4
+ ,IN = 5
+ ,OUT = 6
+ ,ERR = 7
+ ,DATA = 8
+ ,GET_VALUES = 9
+ ,GET_RESULT = 10
+ ,UNKNOWN = 11
+ };
+
+ enum class Role : uint16_t
+ {
+ RESPONDER = 1
+ ,AUTORIZER = 2
+ ,FILTER = 3
+ };
+
+ enum class RequestStatus : uint8_t
+ {
+ REQUEST_COMPLETE = 0
+ ,CANT_MPX_CONN = 1
+ ,OVERLOADED = 2
+ ,UNKNOWN_ROLE = 3
+ };
+
+#pragma pack(push,1)
+
+ struct Header
+ {
+ //! Factgi version
+ uint8_t m_Version;
+ //! Record type
+ RecordType m_Type;
+ //! Request Id
+ bigEndian<uint16_t> m_Id;
+ //! Request length
+ bigEndian<uint16_t> m_Length;
+ //! Padding length
+ uint8_t m_PaddingLength;
+ //! Reserved
+ uint8_t m_Reserved;
+ };
+
+ //
+ //Helper bodies
+ //
+
+ /**
+ *
+ */
+ struct BeginRequest
+ {
+ //!
+ //int m_KeepConn; // Should be always 1
+ //! Role
+ bigEndian<uint16_t> m_Role;
+ //! Flags
+ uint8_t m_Flags;
+ //! reserved
+ uint8_t m_Reserved[5];
+ };
+
+ /**
+ *
+ */
+ struct UnknownType
+ {
+ RecordType m_Type;
+ uint8_t m_Reserved[7];
+ };
+ /**
+ * Named Value Pairs
+ */
+ struct NameValuePairHeader11
+ {
+ uint8_t nameLength;
+ uint8_t valueLength;
+ };
+
+ struct NameValuePairHeader14
+ {
+ uint8_t nameLength;
+ bigEndian<uint32_t> valueLength;
+ };
+
+ struct NameValuePairHeader41
+ {
+ bigEndian<uint32_t> nameLength;
+ uint8_t valueLength;
+ };
+
+ struct NameValuePairHeader44
+ {
+ bigEndian<uint32_t> nameLength;
+ bigEndian<uint32_t> valueLength;
+ };
+#pragma pack(pop)
+ /**
+ *
+ */
+ struct EndRequet
+ {
+ //! Return application request status
+ int32_t m_ApplicationStatus;
+ //! Return Fastcgi protocol status
+ RequestStatus m_ProtocolStatus;
+ //! Reserverd
+ uint8_t m_Reserved[3];
+ };
+
+ /**
+ * @brief
+ */
+ template <typename Descriptor,typename InternetProtocol>
+ class request
+ {
+ private:
+ enum class State : uint32_t {
+ ST_Init
+ , ST_Params
+ , ST_StdIn
+ , ST_StdOut
+ , ST_Error
+ } ;
+ private:
+ /// Reference counter...
+ int m_ref;
+ ///
+ State m_State;
+ public:
+ ///
+ typedef aeb::net::basic_socket_stream<InternetProtocol> Stream;
+ ///
+ typedef aeb::intrusive_ptr<request> ptr;
+
+ request(aeb::fcgi::Header &_h) : m_State(State::ST_Init) , m_Id(_h.m_Id)
+ {
+ }
+ /**
+ * @brief read all parameters
+ */
+ void process_parameters(Stream &_s,uint16_t _length)
+ {
+ char _Buffer[4096];
+ int res = 0;
+ uint16_t _totalRead = 0;
+ NameValuePairHeader11 *_h11 = reinterpret_cast<NameValuePairHeader11 *>(_Buffer);
+ NameValuePairHeader14 *_h14 = reinterpret_cast<NameValuePairHeader14 *>(_Buffer);
+ do {
+ res = _s.receive(_Buffer,2);
+ _totalRead+=res;
+ if ( (_h11->nameLength < 127) && (_h11->valueLength < 127))
+ {
+ res = _s.receive(_Buffer+2,_h11->nameLength + _h11->valueLength);
+ _totalRead+=res;
+ std::string name(_Buffer+2,_h11->nameLength);
+ std::string value(_Buffer+2+_h11->nameLength,_h11->valueLength);
+ std::cout<<"Got Parameter ("<<(int)_h11->nameLength<<","<<(int)_h11->valueLength<<")"<<name<<" "<<value<<std::endl;
+ } else
+ if ( (_h11->nameLength > 127) && (_h11->valueLength < 127))
+ {
+ std::cout<<"not yet 1"<<std::endl;
+ } else
+ if ( (_h11->nameLength < 127) && (_h11->valueLength > 127))
+ {
+ std::cout<<"not yet enter nameLength="<<(int)_h14->nameLength<<" vl="<<(int)_h11->valueLength<<std::endl;
+ res = _s.receive(_Buffer+2,3);
+ _totalRead+=res;
+ // Read name and value
+ res = _s.receive(_Buffer+5,_h11->nameLength + _h14->valueLength & 0x7FFFFFFF);
+ _totalRead+=res;
+ std::string name(_Buffer+5,_h11->nameLength);
+ std::string value(_Buffer+5+_h11->nameLength,_h14->valueLength & 0x7FFFFFFF);
+ std::cout<<"Got Parameter "<<name<<" "<<value<<std::endl;
+ }
+ } while ( _totalRead != _length);
+ //res = _s.receive(_Buffer,2);
+ //std::cout<<"Final Read "<<res<<std::endl;
+ }
+ private:
+ uint16_t m_Id;
+ };
+
+}; // end fcgi
+}; // end aeb
+#endif