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