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,
40 bool unidirectional) OVERRIDE {}
41 virtual void OnSynReply(SpdyStreamId stream_id, bool fin) OVERRIDE {}
42 virtual void OnRstStream(SpdyStreamId stream_id,
43 SpdyRstStreamStatus status) OVERRIDE {}
44 virtual void OnSetting(SpdySettingsIds id,
46 uint32 value) OVERRIDE {}
47 virtual void OnPing(SpdyPingId unique_id) OVERRIDE {}
48 virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
49 SpdyGoAwayStatus status) OVERRIDE {}
50 virtual void OnHeaders(SpdyStreamId stream_id, bool fin) OVERRIDE {}
51 virtual void OnWindowUpdate(SpdyStreamId stream_id,
52 uint32 delta_window_size) OVERRIDE {}
53 virtual void OnPushPromise(SpdyStreamId stream_id,
54 SpdyStreamId promised_stream_id) OVERRIDE {}
55 void set_visitor(QuicSpdyDecompressor::Visitor* visitor) {
61 QuicSpdyDecompressor::Visitor* visitor_;
65 bool SpdyFramerVisitor::OnControlFrameHeaderData(SpdyStreamId stream_id,
66 const char* header_data,
69 return visitor_->OnDecompressedData(StringPiece(header_data, len));
72 QuicSpdyDecompressor::QuicSpdyDecompressor()
73 : spdy_framer_(SPDY3),
74 spdy_visitor_(new SpdyFramerVisitor(NULL)),
75 current_header_id_(1),
76 has_current_compressed_size_(false),
77 current_compressed_size_(0),
78 compressed_bytes_consumed_(0) {
79 spdy_framer_.set_visitor(spdy_visitor_.get());
82 QuicSpdyDecompressor::~QuicSpdyDecompressor() {
85 size_t QuicSpdyDecompressor::DecompressData(StringPiece data,
87 spdy_visitor_->set_visitor(visitor);
88 size_t bytes_consumed = 0;
90 if (!has_current_compressed_size_) {
91 const size_t kCompressedBufferSizeSize = sizeof(uint32);
92 DCHECK_GT(kCompressedBufferSizeSize, compressed_size_buffer_.length());
94 kCompressedBufferSizeSize - compressed_size_buffer_.length();
95 if (data.length() < missing_size) {
96 data.AppendToString(&compressed_size_buffer_);
99 bytes_consumed += missing_size;
100 data.substr(0, missing_size).AppendToString(&compressed_size_buffer_);
101 DCHECK_EQ(kCompressedBufferSizeSize, compressed_size_buffer_.length());
102 memcpy(¤t_compressed_size_, compressed_size_buffer_.data(),
103 kCompressedBufferSizeSize);
104 compressed_size_buffer_.clear();
105 has_current_compressed_size_ = true;
106 data = data.substr(missing_size);
107 compressed_bytes_consumed_ = 0;
110 size_t bytes_to_consume =
111 min(current_compressed_size_ - compressed_bytes_consumed_,
112 static_cast<uint32>(data.length()));
113 if (bytes_to_consume > 0) {
114 if (!spdy_framer_.IncrementallyDecompressControlFrameHeaderData(
115 current_header_id_, data.data(), bytes_to_consume)) {
116 visitor->OnDecompressionError();
117 return bytes_consumed;
119 compressed_bytes_consumed_ += bytes_to_consume;
120 bytes_consumed += bytes_to_consume;
122 if (current_compressed_size_ - compressed_bytes_consumed_ == 0) {
123 ResetForNextHeaders();
125 return bytes_consumed;
128 void QuicSpdyDecompressor::ResetForNextHeaders() {
129 has_current_compressed_size_ = false;
130 current_compressed_size_ = 0;
131 compressed_bytes_consumed_ = 0;
132 ++current_header_id_;