00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <cstdlib>
00011 #include <zlib.h>
00012 #include <iostream>
00013 #include <fstream>
00014 #include <boost/asio/detail/socket_ops.hpp>
00015 #include <pion/spdy/decompressor.hpp>
00016
00017
00018 namespace pion {
00019 namespace spdy {
00020
00021
00022
00023
00024 const char decompressor::SPDY_ZLIB_DICTIONARY[] =
00025 "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-"
00026 "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi"
00027 "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser"
00028 "-agent10010120020120220320420520630030130230330430530630740040140240340440"
00029 "5406407408409410411412413414415416417500501502503504505accept-rangesageeta"
00030 "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic"
00031 "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran"
00032 "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati"
00033 "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo"
00034 "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe"
00035 "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic"
00036 "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1"
00037 ".1statusversionurl";
00038
00039
00040
00041
00042 decompressor::decompressor()
00043 : m_request_zstream(NULL), m_response_zstream(NULL)
00044 {
00045 m_request_zstream = (z_streamp)malloc(sizeof(z_stream));
00046 BOOST_ASSERT(m_request_zstream);
00047
00048 m_request_zstream->zalloc = Z_NULL;
00049 m_request_zstream->zfree = Z_NULL;
00050 m_request_zstream->opaque = Z_NULL;
00051 m_request_zstream->next_in = Z_NULL;
00052 m_request_zstream->next_out = Z_NULL;
00053 m_request_zstream->avail_in = 0;
00054 m_request_zstream->avail_out = 0;
00055
00056 m_response_zstream = (z_streamp)malloc(sizeof(z_stream));
00057 BOOST_ASSERT(m_response_zstream);
00058
00059 m_response_zstream->zalloc = Z_NULL;
00060 m_response_zstream->zfree = Z_NULL;
00061 m_response_zstream->opaque = Z_NULL;
00062 m_response_zstream->next_in = Z_NULL;
00063 m_response_zstream->next_out = Z_NULL;
00064 m_response_zstream->avail_in = 0;
00065 m_response_zstream->avail_out = 0;
00066
00067 int retcode = inflateInit2(m_request_zstream, MAX_WBITS);
00068 if (retcode == Z_OK) {
00069 retcode = inflateInit2(m_response_zstream, MAX_WBITS);
00070 if (retcode == Z_OK) {
00071
00072 m_dictionary_id = adler32(0L, Z_NULL, 0);
00073
00074 m_dictionary_id = adler32(m_dictionary_id,
00075 (const Bytef *)SPDY_ZLIB_DICTIONARY,
00076 sizeof(SPDY_ZLIB_DICTIONARY));
00077 }
00078 }
00079 }
00080
00081 decompressor::~decompressor()
00082 {
00083 inflateEnd(m_request_zstream);
00084 inflateEnd(m_response_zstream);
00085 free(m_request_zstream);
00086 free(m_response_zstream);
00087 }
00088
00089 char* decompressor::decompress(const char *compressed_data_ptr,
00090 boost::uint32_t stream_id,
00091 const spdy_control_frame_info& frame,
00092 boost::uint32_t header_block_length)
00093 {
00095 z_streamp decomp = NULL;
00096 if (stream_id % 2 == 0) {
00097
00098
00099 decomp = m_response_zstream;
00100 } else if (frame.type == SPDY_HEADERS) {
00101
00102
00103
00104 decomp = m_response_zstream;
00105 } else if (frame.type == SPDY_SYN_STREAM) {
00106 decomp = m_request_zstream;
00107 } else if (frame.type == SPDY_SYN_REPLY) {
00108 decomp = m_response_zstream;
00109 } else {
00110
00111 BOOST_ASSERT(false);
00112 }
00113 BOOST_ASSERT(decomp);
00114
00115
00116 boost::uint32_t uncomp_length = 0;
00117
00118
00119 if (!spdy_decompress_header(compressed_data_ptr, decomp,
00120 header_block_length, uncomp_length))
00121 {
00122
00123
00124
00125
00126 return NULL;
00127 }
00128 return reinterpret_cast<char*>(m_uncompressed_header);
00129 }
00130
00131 bool decompressor::spdy_decompress_header(const char *compressed_data_ptr,
00132 z_streamp decomp,
00133 boost::uint32_t length,
00134 boost::uint32_t& uncomp_length) {
00135 int retcode;
00136 const boost::uint8_t *hptr = (boost::uint8_t *)compressed_data_ptr;
00137
00138 decomp->next_in = (Bytef *)hptr;
00139 decomp->avail_in = length;
00140 decomp->next_out = m_uncompressed_header;
00141 decomp->avail_out = MAX_UNCOMPRESSED_DATA_BUF_SIZE;
00142
00143 retcode = inflate(decomp, Z_SYNC_FLUSH);
00144
00145 if (retcode == Z_NEED_DICT) {
00146 if (decomp->adler != m_dictionary_id) {
00147
00148 } else {
00149 retcode = inflateSetDictionary(decomp,
00150 (const Bytef *)SPDY_ZLIB_DICTIONARY,
00151 sizeof(SPDY_ZLIB_DICTIONARY));
00152 if (retcode == Z_OK) {
00153 retcode = inflate(decomp, Z_SYNC_FLUSH);
00154 }
00155 }
00156 }
00157
00158
00159 if (retcode != Z_OK) {
00160
00161
00162
00163 return false;
00164 }
00165
00166
00167 uncomp_length = MAX_UNCOMPRESSED_DATA_BUF_SIZE - decomp->avail_out;
00168 if (decomp->avail_in != 0) {
00169
00170
00171
00172
00173 return false;
00174 }
00175
00176 return true;
00177 }
00178
00179 }
00180 }