00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 #ifndef __PION_SPDYPARSER_HEADER__
00011 #define __PION_SPDYPARSER_HEADER__
00012 
00013 
00014 #include <boost/shared_ptr.hpp>
00015 #include <boost/logic/tribool.hpp>
00016 #include <boost/system/error_code.hpp>
00017 #include <boost/thread/once.hpp>
00018 #include <pion/config.hpp>
00019 #include <pion/logger.hpp>
00020 #include <pion/spdy/types.hpp>
00021 #include <pion/spdy/decompressor.hpp>
00022 
00023 
00024 namespace pion {    
00025 namespace spdy {    
00026 
00027     
00031 
00032 class PION_API parser
00033 {
00034 public:
00035     
00037     enum error_value_t {
00038         ERROR_INVALID_SPDY_FRAME = 1,
00039         ERROR_INVALID_SPDY_VERSION,
00040         ERROR_DECOMPRESSION,
00041         ERROR_PROTOCOL_ERROR,
00042         ERROR_INTERNAL_SPDY_ERROR,
00043         ERROR_MISSING_HEADER_DATA
00044     };
00045     
00047     class error_category_t
00048         : public boost::system::error_category
00049     {
00050     public:
00051         const char *name() const { return "SPDYParser"; }
00052         std::string message(int ev) const {
00053             switch (ev) {
00054                 case ERROR_INVALID_SPDY_FRAME:
00055                     return "invalid spdy frame";
00056                 case ERROR_INVALID_SPDY_VERSION:
00057                     return "invalid spdy version";
00058                 case ERROR_DECOMPRESSION:
00059                     return "error in decompression";
00060                 case ERROR_MISSING_HEADER_DATA:
00061                     return "missing header data";
00062                     
00063             }
00064             return "SPDYParser error";
00065         }
00066     };
00067     
00069     parser();
00070     
00072     ~parser() {}
00073     
00082     boost::tribool parse(http_protocol_info& http_headers,
00083                          boost::system::error_code& ec,
00084                          decompressor_ptr& decompressor,
00085                          const char *packet_ptr,
00086                          boost::uint32_t& length_packet,
00087                          boost::uint32_t current_stream_count);
00088     
00090     const char * get_spdy_data_content( ) { return m_last_data_chunk_ptr; }
00091     
00093     const char * get_spdy_read_pointer( ) { return m_read_ptr; }
00094     
00100     static spdy_frame_type get_spdy_frame_type(const char *ptr);
00101     
00107     static bool is_spdy_control_frame(const char *ptr);
00108     
00114     static boost::uint32_t get_control_frame_stream_id(const char *ptr);
00115     
00116     
00117 protected:
00118     
00120     inline void set_read_ptr(const char *ptr) { m_read_ptr = m_current_data_chunk_ptr = ptr; }
00121     
00124     bool populate_frame(boost::system::error_code& ec,
00125                         spdy_control_frame_info& frame,
00126                         boost::uint32_t& length_packet,
00127                         boost::uint32_t& stream_id,
00128                         http_protocol_info& http_headers);
00129     
00131     static void create_error_category(void);
00132     
00134     static inline error_category_t& get_error_category(void) {
00135         boost::call_once(parser::create_error_category, m_instance_flag);
00136         return *m_error_category_ptr;
00137     }
00138 
00145     static inline void set_error(boost::system::error_code& ec, error_value_t ev) {
00146         ec = boost::system::error_code(static_cast<int>(ev), get_error_category());
00147     }
00148     
00153     void parse_header_payload(boost::system::error_code& ec,
00154                               decompressor_ptr& decompressor,
00155                               const spdy_control_frame_info& frame,
00156                               http_protocol_info& http_headers,
00157                               boost::uint32_t current_stream_count);
00158     
00163     void parse_spdy_data(boost::system::error_code& ec,
00164                          const spdy_control_frame_info& frame,
00165                          boost::uint32_t stream_id,
00166                          http_protocol_info& http_info);
00167     
00172     void parse_spdy_settings_frame(boost::system::error_code& ec,
00173                                    const spdy_control_frame_info& frame);
00174     
00179     void parse_spdy_rst_stream(boost::system::error_code& ec,
00180                                const spdy_control_frame_info& frame);
00181     
00186     void parse_spdy_ping_frame(boost::system::error_code& ec,
00187                                const spdy_control_frame_info& frame);
00188     
00193     void parse_spdy_goaway_frame(boost::system::error_code& ec,
00194                                  const spdy_control_frame_info& frame);
00195     
00200     void parse_spdy_window_update_frame(boost::system::error_code& ec,
00201                                         const spdy_control_frame_info& frame);
00202     
00211     boost::tribool parse_spdy_frame(boost::system::error_code& ec,
00212                                     decompressor_ptr& decompressor,
00213                                     http_protocol_info& http_headers,
00214                                     boost::uint32_t& length_packet,
00215                                     boost::uint32_t current_stream_count);
00216     
00217 private:
00218     
00220     const char *                        m_read_ptr;
00221     
00223     const char *                        m_uncompressed_ptr;
00224     
00226     const char *                        m_current_data_chunk_ptr;
00227     
00229     const char *                        m_last_data_chunk_ptr;
00230     
00232     mutable logger                      m_logger;
00233     
00235     static error_category_t *           m_error_category_ptr;
00236     
00238     static boost::once_flag             m_instance_flag;
00239 };
00240 
00242 typedef boost::shared_ptr<parser>       parser_ptr;
00243         
00244         
00245 }   
00246 }   
00247 
00248 #endif
00249