00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 #include <cstdlib>
00011 #include <boost/regex.hpp>
00012 #include <boost/logic/tribool.hpp>
00013 #include <boost/asio/detail/socket_ops.hpp>
00014 #include <pion/algorithm.hpp>
00015 #include <pion/spdy/parser.hpp>
00016 #include <pion/spdy/decompressor.hpp>
00017 #include <pion/spdy/types.hpp>
00018 
00019 
00020 namespace pion {    
00021 namespace spdy {    
00022 
00024 static char const* rst_stream_status(boost::uint32_t rst_stream_status_code)
00025 {
00026     switch (rst_stream_status_code)
00027     {
00028     case  1: return "PROTOCOL_ERROR";
00029     case  2: return "INVALID_STREAM";
00030     case  3: return "REFUSED_STREAM";
00031     case  4: return "UNSUPPORTED_VERSION";
00032     case  5: return "CANCEL";
00033     case  6: return "INTERNAL_ERROR";
00034     case  7: return "FLOW_CONTROL_ERROR";
00035     case  8: return "STREAM_IN_USE";
00036     case  9: return "STREAM_ALREADY_CLOSED";
00037     case 10: return "INVALID_CREDENTIALS";
00038     case 11: return "FRAME_TOO_LARGE";
00039     case 12: return "INVALID";
00040     default: return NULL;
00041     }
00042 }
00043 
00044 parser::error_category_t *  parser::m_error_category_ptr = NULL;
00045 boost::once_flag            parser::m_instance_flag = BOOST_ONCE_INIT;
00046 
00047 
00048 
00049 parser::parser()
00050     : m_read_ptr(NULL),
00051     m_uncompressed_ptr(NULL),
00052     m_current_data_chunk_ptr(NULL),
00053     m_last_data_chunk_ptr(NULL),
00054     m_logger(PION_GET_LOGGER("pion.spdy.parser"))
00055 {}
00056 
00057 boost::tribool parser::parse(http_protocol_info& http_info,
00058                              boost::system::error_code& ec,
00059                              decompressor_ptr& decompressor,
00060                              const char *packet_ptr,
00061                              boost::uint32_t& length_packet,
00062                              boost::uint32_t current_stream_count)
00063 {
00064     
00065     set_read_ptr(packet_ptr);
00066     
00067     
00068     return parse_spdy_frame(ec, decompressor, http_info, length_packet, current_stream_count);
00069 }
00070 
00071 bool parser::is_spdy_control_frame(const char *ptr)
00072 {
00073     
00074     
00075     
00076     boost::uint8_t control_bit;
00077     boost::uint16_t version, type;
00078     boost::uint16_t byte_value = algorithm::to_uint16(ptr);
00079     control_bit = byte_value >> (sizeof(short) * CHAR_BIT - 1);
00080 
00081     if (!control_bit) return false;
00082     
00083     
00084     
00085     
00086     boost::uint16_t two_bytes = algorithm::to_uint16(ptr);
00087     version = two_bytes & 0x7FFF;
00088     
00089     if(version < 1 || version > 3){
00090         
00091         return false;
00092     }
00093     
00094     
00095     ptr += 2;
00096     
00097     type = algorithm::to_uint16(ptr);
00098     
00099     if (type >= SPDY_INVALID) {
00100         
00101         return false;
00102     }
00103     
00104     return true;
00105 }
00106 
00107 spdy_frame_type parser::get_spdy_frame_type(const char *ptr)
00108 {
00109     
00110     BOOST_ASSERT(ptr);
00111 
00112     
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120     
00121     spdy_frame_type spdy_frame;
00122     boost::uint8_t first_byte = *((unsigned char *)ptr);
00123     if(first_byte == 0x80){
00124         spdy_frame = spdy_control_frame;
00125     }else if(first_byte == 0x0){
00126         spdy_frame = spdy_data_frame;
00127     }else{
00128         spdy_frame = spdy_invalid_frame;
00129     }
00130     return spdy_frame;
00131 }
00132     
00133 boost::uint32_t parser::get_control_frame_stream_id(const char *ptr)
00134 {
00135     
00136     ptr += 8;
00137 
00138     boost::uint32_t four_bytes = algorithm::to_uint32(ptr);
00139     return four_bytes & 0x7FFFFFFF;
00140 }
00141     
00142 boost::tribool parser::parse_spdy_frame(boost::system::error_code& ec,
00143                                         decompressor_ptr& decompressor,
00144                                         http_protocol_info& http_info,
00145                                         boost::uint32_t& length_packet,
00146                                         boost::uint32_t current_stream_count)
00147 {
00148     boost::tribool rc = true;
00149     
00150     
00151     
00152     BOOST_ASSERT(m_read_ptr);
00153     boost::uint8_t first_byte = (boost::uint8_t)*m_read_ptr;
00154     if (first_byte != 0x80 && first_byte != 0x0) {
00155         
00156         PION_LOG_ERROR(m_logger, "Invalid SPDY Frame");
00157         set_error(ec, ERROR_INVALID_SPDY_FRAME);
00158         return false;
00159     }
00160     
00161     boost::uint8_t              control_bit;
00162     spdy_control_frame_info     frame;
00163     boost::uint32_t             stream_id = 0;
00164     
00165     ec.clear();
00166 
00167     
00168     bool populate_frame_result = populate_frame(ec, frame, length_packet, stream_id, http_info);
00169     
00170     if(!populate_frame_result){
00172         return false;
00173     }
00174     
00175     BOOST_ASSERT(stream_id != 0);
00176     
00177     control_bit = (boost::uint8_t)frame.control_bit;
00178     
00179     
00180     if(length_packet > frame.length){
00181         m_current_data_chunk_ptr = m_read_ptr + frame.length;
00182         length_packet -= frame.length;
00183         rc = boost::indeterminate;
00184     }
00185     
00186     if (!control_bit) {
00187         
00188         parse_spdy_data(ec, frame, stream_id, http_info);
00189     }
00190     
00191     
00192     
00193     if (frame.version > MIN_SPDY_VERSION) {
00194         
00195         PION_LOG_ERROR(m_logger, "Invalid SPDY Version Number");
00196         set_error(ec, ERROR_INVALID_SPDY_VERSION);
00197         return false;
00198     }
00199     
00200     if(frame.type ==  SPDY_SYN_STREAM){
00201         http_info.http_type = HTTP_REQUEST;
00202     }else if (frame.type == SPDY_SYN_REPLY){
00203         http_info.http_type = HTTP_RESPONSE;
00204     }else if (frame.type == SPDY_DATA){
00205         http_info.http_type = HTTP_DATA;
00206     }
00207 
00208     switch (frame.type) {
00209         case SPDY_SYN_STREAM:
00210         case SPDY_SYN_REPLY:
00211         case SPDY_HEADERS:
00212             parse_header_payload(ec, decompressor, frame, http_info, current_stream_count);
00213             break;
00214             
00215         case SPDY_RST_STREAM:
00216             parse_spdy_rst_stream(ec, frame);
00217             http_info.http_type = SPDY_CONTROL;
00218             break;
00219             
00220         case SPDY_SETTINGS:
00221             parse_spdy_settings_frame(ec, frame);
00222             http_info.http_type = SPDY_CONTROL;
00223             break;
00224             
00225         case SPDY_PING:
00226             parse_spdy_ping_frame(ec, frame);
00227             http_info.http_type = SPDY_CONTROL;
00228             break;
00229             
00230         case SPDY_GOAWAY:
00231             parse_spdy_goaway_frame(ec, frame);
00232             http_info.http_type = SPDY_CONTROL;
00233             break;
00234             
00235         case SPDY_WINDOW_UPDATE:
00236             parse_spdy_window_update_frame(ec, frame);
00237             http_info.http_type = SPDY_CONTROL;
00238             break;
00239             
00240         case SPDY_CREDENTIAL:
00241             
00242             http_info.http_type = SPDY_CONTROL;
00243             break;
00244             
00245         default:
00246             break;
00247     }
00248     
00249     if (ec)
00250         return false;
00251     
00252     m_last_data_chunk_ptr = m_read_ptr;
00253     m_read_ptr = m_current_data_chunk_ptr;
00254     
00255     return rc;
00256 }
00257 
00258 void parser::create_error_category(void)
00259 {
00260     static error_category_t UNIQUE_ERROR_CATEGORY;
00261     m_error_category_ptr = &UNIQUE_ERROR_CATEGORY;
00262 }
00263 
00264 bool parser::populate_frame(boost::system::error_code& ec,
00265                             spdy_control_frame_info& frame,
00266                             boost::uint32_t& length_packet,
00267                             boost::uint32_t& stream_id,
00268                             http_protocol_info& http_info)
00269 {
00270     
00271     boost::uint8_t control_bit;
00272     boost::uint16_t byte_value = algorithm::to_uint16(m_read_ptr);
00273     control_bit = byte_value >> (sizeof(short) * CHAR_BIT - 1);
00274     
00275     frame.control_bit = (control_bit != 0);
00276     
00277     if(control_bit){
00278         
00279         
00280         
00281         
00282         boost::uint16_t two_bytes = algorithm::to_uint16(m_read_ptr);
00283         frame.version = two_bytes & 0x7FFF;
00284         
00285         
00286         m_read_ptr += 2;
00287         length_packet -= 2;
00288         http_info.data_offset +=2;
00289         
00290         
00291         frame.type = algorithm::to_uint16(m_read_ptr);
00292         
00293         if (frame.type >= SPDY_INVALID) {
00294             
00295             
00296             
00297             PION_LOG_ERROR(m_logger, "Invalid SPDY Frame");
00298             set_error(ec, ERROR_INVALID_SPDY_FRAME);
00299             return false;
00300         }
00301     }else {
00302         
00303         
00304         
00305         frame.type = SPDY_DATA;
00306         frame.version = 0; 
00307         
00308         boost::uint32_t four_bytes = algorithm::to_uint32(m_read_ptr);
00309         stream_id = four_bytes & 0x7FFFFFFF;
00310         
00311         http_info.stream_id = stream_id;
00312         
00313         m_read_ptr +=2;
00314         http_info.data_offset +=2;
00315         length_packet -= 2;
00316         
00317     }
00318     
00319     
00320     m_read_ptr += 2;
00321     length_packet -= 2;
00322     http_info.data_offset +=2;
00323     
00324     
00325     frame.flags = (boost::uint8_t)*m_read_ptr;
00326     
00327     
00328     
00329     
00330     boost::uint32_t four_bytes = algorithm::to_uint32(m_read_ptr);
00331     frame.length = four_bytes & 0xFFFFFF;
00332     
00333     
00334     m_read_ptr += 4;
00335     length_packet -= 4;
00336     http_info.data_offset +=4;
00337     
00338     http_info.data_size = frame.length;
00339     
00340     if(control_bit){
00341         four_bytes = algorithm::to_uint32(m_read_ptr);
00342         stream_id = four_bytes & 0x7FFFFFFF;
00343     }
00344     
00345     return true;
00346 }
00347 
00348 void parser::parse_header_payload(boost::system::error_code &ec,
00349                                   decompressor_ptr& decompressor,
00350                                   const spdy_control_frame_info& frame,
00351                                   http_protocol_info& http_info,
00352                                   boost::uint32_t current_stream_count)
00353 {
00354     boost::uint32_t stream_id = 0;
00355     boost::uint32_t associated_stream_id;
00356     boost::uint32_t header_block_length = frame.length;
00357     
00358     
00359     
00360     boost::uint32_t four_bytes = algorithm::to_uint32(m_read_ptr);
00361     stream_id = four_bytes & 0x7FFFFFFF;
00362     
00363     m_read_ptr += 4;
00364     
00365     http_info.stream_id = stream_id;
00366     
00367     
00368     
00369     if (frame.type == SPDY_SYN_STREAM) {
00370         
00371         
00372         
00373         boost::uint32_t four_bytes = algorithm::to_uint32(m_read_ptr);
00374         associated_stream_id = four_bytes & 0x7FFFFFFF;
00375         
00376         m_read_ptr += 4;
00377         
00378         
00379         
00380         
00381         m_read_ptr +=2 ;
00382         
00383     } else if( frame.type == SPDY_SYN_REPLY || frame.type == SPDY_HEADERS ) {
00384         
00385         
00386         m_read_ptr +=2 ;
00387     }
00388     
00389     
00390     
00391     switch (frame.type) {
00392         case SPDY_SYN_STREAM:
00393             header_block_length -= 10;
00394             break;
00395         case SPDY_SYN_REPLY:
00396         case SPDY_HEADERS:
00397             
00398             
00399             header_block_length -= 6;
00400             break;
00401         default:
00402             
00403             PION_LOG_ERROR(m_logger, "Invalid SPDY Frame Type");
00404             set_error(ec, ERROR_INVALID_SPDY_FRAME);
00405             return;
00406     }
00407     
00408     
00409     m_uncompressed_ptr = decompressor->decompress(m_read_ptr,
00410                                                   stream_id,
00411                                                   frame,
00412                                                   header_block_length);
00413     
00414     if (!m_uncompressed_ptr) {
00415         set_error(ec, ERROR_DECOMPRESSION);
00416         return;
00417     }
00418         
00419     
00420     
00421     
00422     
00423     
00424     
00425     boost::uint16_t num_name_val_pairs = algorithm::to_uint16(m_uncompressed_ptr);
00426     
00427     m_uncompressed_ptr += 2;
00428     
00429     std::string content_type = "";
00430     std::string content_encoding = "";
00431     
00432     for(boost::uint16_t count = 0; count < num_name_val_pairs; ++count){
00433         
00434         
00435         
00436         boost::uint16_t length_name = algorithm::to_uint16(m_uncompressed_ptr);
00437         std::string name = "";
00438         
00439         m_uncompressed_ptr += 2;
00440         
00441         {
00442             for(boost::uint16_t count = 0; count < length_name; ++count){
00443                 name.push_back(*(m_uncompressed_ptr+count));
00444             }
00445             m_uncompressed_ptr += length_name;
00446         }
00447         
00448         
00449         boost::uint16_t length_value = algorithm::to_uint16(m_uncompressed_ptr);
00450         std::string value = "";
00451         
00452         m_uncompressed_ptr += 2;
00453         
00454         {
00455             for(boost::uint16_t count = 0; count < length_value; ++count){
00456                 value.push_back(*(m_uncompressed_ptr+count));
00457             }
00458             m_uncompressed_ptr += length_value;
00459         }
00460         
00461         
00462         http_info.http_headers.insert(std::make_pair(name, value));
00463     }
00464 }
00465 
00466 void parser::parse_spdy_data(boost::system::error_code &ec,
00467                              const spdy_control_frame_info& frame,
00468                              boost::uint32_t stream_id,
00469                              http_protocol_info& http_info)
00470 {
00471     
00472     if (frame.flags & SPDY_FLAG_FIN){
00473         http_info.last_chunk = true;
00474     }
00475 }
00476 
00477 void parser::parse_spdy_rst_stream(boost::system::error_code &ec,
00478                                    const spdy_control_frame_info& frame)
00479 {
00480     boost::uint32_t stream_id = 0;
00481     boost::uint32_t status_code = 0;
00482     
00483     
00484     
00485     if(frame.flags != 0 || frame.length != 8 ){
00486         return;
00487     }
00488 
00489     
00490     
00491     boost::uint32_t four_bytes = algorithm::to_uint32(m_read_ptr);
00492     stream_id = four_bytes & 0x7FFFFFFF;
00493     
00494     m_read_ptr += 4;
00495     
00496     
00497     
00498     status_code = algorithm::to_uint32(m_read_ptr);
00499     
00500     char const* const status_code_str = rst_stream_status(status_code);
00501     if(status_code_str){
00502         PION_LOG_INFO(m_logger, "SPDY Status Code is : " << status_code_str);
00503     }else{
00504         PION_LOG_INFO(m_logger, "SPDY RST Invalid status code : " << status_code);
00505     }
00506 }
00507 
00508 void parser::parse_spdy_ping_frame(boost::system::error_code &ec,
00509                                    const spdy_control_frame_info& frame)
00510 {
00511     
00512     
00513     if(frame.length != 4){
00514         return;
00515     }
00516   
00517     boost::uint32_t ping_id = 0;
00518     
00519     
00520     
00521     ping_id = algorithm::to_uint32(m_read_ptr);
00522     
00523     m_read_ptr += 4;
00524     
00525     PION_LOG_INFO(m_logger, "SPDY " << "Ping ID is : " << ping_id);
00526 }
00527 
00528 void parser::parse_spdy_settings_frame(boost::system::error_code &ec,
00529                                        const spdy_control_frame_info& frame)
00530 {
00531     
00532 }
00533 
00534 void parser::parse_spdy_goaway_frame(boost::system::error_code &ec,
00535                                      const spdy_control_frame_info& frame)
00536 {
00537     
00538     
00539     if(frame.length != 4){
00540         return;
00541     }
00542     
00543     boost::uint32_t last_good_stream_id = 0;
00544     boost::uint32_t status_code = 0;
00545     
00546     
00547     
00548     boost::uint32_t four_bytes = algorithm::to_uint32(m_read_ptr);
00549     last_good_stream_id = four_bytes & 0x7FFFFFFF;
00550     
00551     m_read_ptr += 4;
00552     
00553     
00554     
00555     status_code = algorithm::to_uint32(m_read_ptr);
00556     
00557     
00558     if(status_code == 1){
00559         
00560         PION_LOG_ERROR(m_logger, "There was a Protocol Error");
00561         set_error(ec, ERROR_PROTOCOL_ERROR);
00562         return;
00563     }else if (status_code == 11) {
00564         
00565         PION_LOG_ERROR(m_logger, "There was an Internal Error");
00566         set_error(ec, ERROR_INTERNAL_SPDY_ERROR);
00567         return;
00568     }
00569     
00570     PION_LOG_INFO(m_logger, "SPDY " << "Status Code is : " << status_code);
00571     
00572 }
00573 
00574 void parser::parse_spdy_window_update_frame(boost::system::error_code &ec,
00575                                             const spdy_control_frame_info& frame)
00576 {
00577     
00578 }
00579     
00580 }   
00581 }