~ubuntu-branches/debian/sid/pion/sid

« back to all changes in this revision

Viewing changes to src/spdy_decompressor.cpp

  • Committer: Package Import Robot
  • Author(s): Roberto C. Sanchez
  • Date: 2013-07-06 18:04:35 UTC
  • Revision ID: package-import@ubuntu.com-20130706180435-kejjzc1qpyz3qv6c
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// ---------------------------------------------------------------------
 
2
// pion:  a Boost C++ framework for building lightweight HTTP interfaces
 
3
// ---------------------------------------------------------------------
 
4
// Copyright (C) 2007-2012 Cloudmeter, Inc.  (http://www.cloudmeter.com)
 
5
//
 
6
// Distributed under the Boost Software License, Version 1.0.
 
7
// See http://www.boost.org/LICENSE_1_0.txt
 
8
//
 
9
 
 
10
#include <cstdlib>
 
11
#include <zlib.h>
 
12
#include <iostream>
 
13
#include <fstream>
 
14
#include <boost/asio/detail/socket_ops.hpp>
 
15
#include <pion/spdy/decompressor.hpp>
 
16
 
 
17
 
 
18
namespace pion {    // begin namespace pion
 
19
namespace spdy {    // begin namespace spdy 
 
20
 
 
21
 
 
22
// decompressor static members
 
23
    
 
24
const char decompressor::SPDY_ZLIB_DICTIONARY[] =
 
25
    "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-"
 
26
    "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi"
 
27
    "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser"
 
28
    "-agent10010120020120220320420520630030130230330430530630740040140240340440"
 
29
    "5406407408409410411412413414415416417500501502503504505accept-rangesageeta"
 
30
    "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic"
 
31
    "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran"
 
32
    "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati"
 
33
    "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo"
 
34
    "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe"
 
35
    "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic"
 
36
    "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1"
 
37
    ".1statusversionurl";
 
38
    
 
39
 
 
40
// decompressor member functions
 
41
 
 
42
decompressor::decompressor()
 
43
    : m_request_zstream(NULL), m_response_zstream(NULL)
 
44
{
 
45
    m_request_zstream = (z_streamp)malloc(sizeof(z_stream));
 
46
    BOOST_ASSERT(m_request_zstream);
 
47
 
 
48
    m_request_zstream->zalloc = Z_NULL;
 
49
    m_request_zstream->zfree = Z_NULL;
 
50
    m_request_zstream->opaque = Z_NULL;
 
51
    m_request_zstream->next_in = Z_NULL;
 
52
    m_request_zstream->next_out = Z_NULL;
 
53
    m_request_zstream->avail_in = 0;
 
54
    m_request_zstream->avail_out = 0;
 
55
    
 
56
    m_response_zstream = (z_streamp)malloc(sizeof(z_stream));
 
57
    BOOST_ASSERT(m_response_zstream);
 
58
    
 
59
    m_response_zstream->zalloc = Z_NULL;
 
60
    m_response_zstream->zfree = Z_NULL;
 
61
    m_response_zstream->opaque = Z_NULL;
 
62
    m_response_zstream->next_in = Z_NULL;
 
63
    m_response_zstream->next_out = Z_NULL;
 
64
    m_response_zstream->avail_in = 0;
 
65
    m_response_zstream->avail_out = 0;
 
66
    
 
67
    int retcode = inflateInit2(m_request_zstream, MAX_WBITS);
 
68
    if (retcode == Z_OK) {
 
69
        retcode = inflateInit2(m_response_zstream, MAX_WBITS);
 
70
        if (retcode == Z_OK) {
 
71
            // Get the dictionary id
 
72
            m_dictionary_id = adler32(0L, Z_NULL, 0);
 
73
            
 
74
            m_dictionary_id = adler32(m_dictionary_id,
 
75
                                      (const Bytef *)SPDY_ZLIB_DICTIONARY,
 
76
                                      sizeof(SPDY_ZLIB_DICTIONARY));
 
77
        }
 
78
    }
 
79
}
 
80
 
 
81
decompressor::~decompressor()
 
82
{
 
83
    inflateEnd(m_request_zstream);
 
84
    inflateEnd(m_response_zstream);
 
85
    free(m_request_zstream);
 
86
    free(m_response_zstream);
 
87
}
 
88
 
 
89
char* decompressor::decompress(const char *compressed_data_ptr,
 
90
                               boost::uint32_t stream_id,
 
91
                               const spdy_control_frame_info& frame,
 
92
                               boost::uint32_t header_block_length)
 
93
{
 
94
    /// Get our decompressor.
 
95
    z_streamp decomp = NULL;
 
96
    if (stream_id % 2 == 0) {
 
97
        // Even streams are server-initiated and should never get a
 
98
        // client-initiated header block. Use reply decompressor.
 
99
        decomp = m_response_zstream;
 
100
    } else if (frame.type == SPDY_HEADERS) {
 
101
        // Odd streams are client-initiated, but may have HEADERS from either
 
102
        // side. Currently, no known clients send HEADERS so we assume they are
 
103
        // all from the server.
 
104
        decomp = m_response_zstream;
 
105
    } else if (frame.type == SPDY_SYN_STREAM) {
 
106
        decomp = m_request_zstream;
 
107
    } else if (frame.type == SPDY_SYN_REPLY) {
 
108
        decomp = m_response_zstream;
 
109
    } else {
 
110
        // Unhandled case. This should never happen.
 
111
        BOOST_ASSERT(false);
 
112
    }
 
113
    BOOST_ASSERT(decomp);
 
114
    
 
115
    // Decompress the data
 
116
    boost::uint32_t uncomp_length = 0;
 
117
    
 
118
    // Catch decompression failures.
 
119
    if (!spdy_decompress_header(compressed_data_ptr, decomp,
 
120
                                header_block_length, uncomp_length))
 
121
    {
 
122
        // Error in decompressing
 
123
        // This error is not catastrophic as many times we might get inconsistent
 
124
        // spdy header frames and we should just log error and continue.
 
125
        // No need to call SetError()
 
126
        return NULL;
 
127
    }
 
128
    return reinterpret_cast<char*>(m_uncompressed_header);
 
129
}
 
130
 
 
131
bool decompressor::spdy_decompress_header(const char *compressed_data_ptr,
 
132
                                          z_streamp decomp,
 
133
                                          boost::uint32_t length,
 
134
                                          boost::uint32_t& uncomp_length) {
 
135
    int retcode;
 
136
    const boost::uint8_t *hptr = (boost::uint8_t *)compressed_data_ptr;
 
137
    
 
138
    decomp->next_in = (Bytef *)hptr;
 
139
    decomp->avail_in = length;
 
140
    decomp->next_out = m_uncompressed_header;
 
141
    decomp->avail_out = MAX_UNCOMPRESSED_DATA_BUF_SIZE;
 
142
    
 
143
    retcode = inflate(decomp, Z_SYNC_FLUSH);
 
144
    
 
145
    if (retcode == Z_NEED_DICT) {
 
146
        if (decomp->adler != m_dictionary_id) {
 
147
            // Decompressor wants a different dictionary id
 
148
        } else {
 
149
            retcode = inflateSetDictionary(decomp,
 
150
                                           (const Bytef *)SPDY_ZLIB_DICTIONARY,
 
151
                                           sizeof(SPDY_ZLIB_DICTIONARY));
 
152
            if (retcode == Z_OK) {
 
153
                retcode = inflate(decomp, Z_SYNC_FLUSH);
 
154
            }
 
155
        }
 
156
    }
 
157
    
 
158
    // Handle Errors. 
 
159
    if (retcode != Z_OK) {
 
160
        // This error is not catastrophic as many times we might get inconsistent
 
161
        // spdy header frames and we should just log error and continue.
 
162
        // No need to call SetError()
 
163
        return false;
 
164
    }
 
165
    
 
166
    // Handle successful inflation. 
 
167
    uncomp_length = MAX_UNCOMPRESSED_DATA_BUF_SIZE - decomp->avail_out;
 
168
    if (decomp->avail_in != 0) {
 
169
        // Error condition
 
170
        // This error is not catastrophic as many times we might get inconsistent
 
171
        // spdy header frames and we should just log error and continue.
 
172
        // No need to call SetError()
 
173
        return false;
 
174
    }
 
175
    
 
176
    return true;
 
177
}
 
178
        
 
179
}   // end namespace spdy
 
180
}   // end namespace pion