1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/quic/quic_spdy_decompressor.h"
9 #include "base/logging.h"
11 using base::StringPiece
;
16 class SpdyFramerVisitor
: public SpdyFramerVisitorInterface
{
18 explicit SpdyFramerVisitor(QuicSpdyDecompressor::Visitor
* visitor
)
23 virtual void OnError(SpdyFramer
* framer
) OVERRIDE
{
26 virtual void OnDataFrameHeader(SpdyStreamId stream_id
,
29 virtual void OnStreamFrameData(SpdyStreamId stream_id
,
33 virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id
,
34 const char* header_data
,
36 virtual void OnSynStream(SpdyStreamId stream_id
,
37 SpdyStreamId associated_stream_id
,
38 SpdyPriority priority
,
39 uint8 credential_slot
,
41 bool unidirectional
) OVERRIDE
{}
42 virtual void OnSynReply(SpdyStreamId stream_id
, bool fin
) OVERRIDE
{}
43 virtual void OnRstStream(SpdyStreamId stream_id
,
44 SpdyRstStreamStatus status
) OVERRIDE
{}
45 virtual void OnSetting(SpdySettingsIds id
,
47 uint32 value
) OVERRIDE
{}
48 virtual void OnPing(uint32 unique_id
) OVERRIDE
{}
49 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id
,
50 SpdyGoAwayStatus status
) OVERRIDE
{}
51 virtual void OnHeaders(SpdyStreamId stream_id
, bool fin
) OVERRIDE
{}
52 virtual void OnWindowUpdate(SpdyStreamId stream_id
,
53 uint32 delta_window_size
) OVERRIDE
{}
54 virtual bool OnCredentialFrameData(const char* credential_data
,
55 size_t len
) OVERRIDE
{
58 virtual void OnPushPromise(SpdyStreamId stream_id
,
59 SpdyStreamId promised_stream_id
) OVERRIDE
{}
60 void set_visitor(QuicSpdyDecompressor::Visitor
* visitor
) {
66 QuicSpdyDecompressor::Visitor
* visitor_
;
70 bool SpdyFramerVisitor::OnControlFrameHeaderData(SpdyStreamId stream_id
,
71 const char* header_data
,
74 return visitor_
->OnDecompressedData(StringPiece(header_data
, len
));
77 QuicSpdyDecompressor::QuicSpdyDecompressor()
78 : spdy_framer_(SPDY3
),
79 spdy_visitor_(new SpdyFramerVisitor(NULL
)),
80 current_header_id_(1),
81 has_current_compressed_size_(false),
82 current_compressed_size_(0),
83 compressed_bytes_consumed_(0) {
84 spdy_framer_
.set_visitor(spdy_visitor_
.get());
87 QuicSpdyDecompressor::~QuicSpdyDecompressor() {
90 size_t QuicSpdyDecompressor::DecompressData(StringPiece data
,
92 spdy_visitor_
->set_visitor(visitor
);
93 size_t bytes_consumed
= 0;
95 if (!has_current_compressed_size_
) {
96 const size_t kCompressedBufferSizeSize
= sizeof(uint32
);
97 DCHECK_GT(kCompressedBufferSizeSize
, compressed_size_buffer_
.length());
99 kCompressedBufferSizeSize
- compressed_size_buffer_
.length();
100 if (data
.length() < missing_size
) {
101 data
.AppendToString(&compressed_size_buffer_
);
102 return data
.length();
104 bytes_consumed
+= missing_size
;
105 data
.substr(0, missing_size
).AppendToString(&compressed_size_buffer_
);
106 DCHECK_EQ(kCompressedBufferSizeSize
, compressed_size_buffer_
.length());
107 memcpy(¤t_compressed_size_
, compressed_size_buffer_
.data(),
108 kCompressedBufferSizeSize
);
109 compressed_size_buffer_
.clear();
110 has_current_compressed_size_
= true;
111 data
= data
.substr(missing_size
);
112 compressed_bytes_consumed_
= 0;
115 size_t bytes_to_consume
=
116 min(current_compressed_size_
- compressed_bytes_consumed_
,
117 static_cast<uint32
>(data
.length()));
118 if (bytes_to_consume
> 0) {
119 if (!spdy_framer_
.IncrementallyDecompressControlFrameHeaderData(
120 current_header_id_
, data
.data(), bytes_to_consume
)) {
121 visitor
->OnDecompressionError();
122 return bytes_consumed
;
124 compressed_bytes_consumed_
+= bytes_to_consume
;
125 bytes_consumed
+= bytes_to_consume
;
127 if (current_compressed_size_
- compressed_bytes_consumed_
== 0) {
128 ResetForNextHeaders();
130 return bytes_consumed
;
133 void QuicSpdyDecompressor::ResetForNextHeaders() {
134 has_current_compressed_size_
= false;
135 current_compressed_size_
= 0;
136 compressed_bytes_consumed_
= 0;
137 ++current_header_id_
;