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 void OnPushPromise(SpdyStreamId stream_id,
55 SpdyStreamId promised_stream_id) OVERRIDE {}
56 void set_visitor(QuicSpdyDecompressor::Visitor* visitor) {
62 QuicSpdyDecompressor::Visitor* visitor_;
66 bool SpdyFramerVisitor::OnControlFrameHeaderData(SpdyStreamId stream_id,
67 const char* header_data,
70 return visitor_->OnDecompressedData(StringPiece(header_data, len));
73 QuicSpdyDecompressor::QuicSpdyDecompressor()
74 : spdy_framer_(SPDY3),
75 spdy_visitor_(new SpdyFramerVisitor(NULL)),
76 current_header_id_(1),
77 has_current_compressed_size_(false),
78 current_compressed_size_(0),
79 compressed_bytes_consumed_(0) {
80 spdy_framer_.set_visitor(spdy_visitor_.get());
83 QuicSpdyDecompressor::~QuicSpdyDecompressor() {
86 size_t QuicSpdyDecompressor::DecompressData(StringPiece data,
88 spdy_visitor_->set_visitor(visitor);
89 size_t bytes_consumed = 0;
91 if (!has_current_compressed_size_) {
92 const size_t kCompressedBufferSizeSize = sizeof(uint32);
93 DCHECK_GT(kCompressedBufferSizeSize, compressed_size_buffer_.length());
95 kCompressedBufferSizeSize - compressed_size_buffer_.length();
96 if (data.length() < missing_size) {
97 data.AppendToString(&compressed_size_buffer_);
100 bytes_consumed += missing_size;
101 data.substr(0, missing_size).AppendToString(&compressed_size_buffer_);
102 DCHECK_EQ(kCompressedBufferSizeSize, compressed_size_buffer_.length());
103 memcpy(¤t_compressed_size_, compressed_size_buffer_.data(),
104 kCompressedBufferSizeSize);
105 compressed_size_buffer_.clear();
106 has_current_compressed_size_ = true;
107 data = data.substr(missing_size);
108 compressed_bytes_consumed_ = 0;
111 size_t bytes_to_consume =
112 min(current_compressed_size_ - compressed_bytes_consumed_,
113 static_cast<uint32>(data.length()));
114 if (bytes_to_consume > 0) {
115 if (!spdy_framer_.IncrementallyDecompressControlFrameHeaderData(
116 current_header_id_, data.data(), bytes_to_consume)) {
117 visitor->OnDecompressionError();
118 return bytes_consumed;
120 compressed_bytes_consumed_ += bytes_to_consume;
121 bytes_consumed += bytes_to_consume;
123 if (current_compressed_size_ - compressed_bytes_consumed_ == 0) {
124 ResetForNextHeaders();
126 return bytes_consumed;
129 void QuicSpdyDecompressor::ResetForNextHeaders() {
130 has_current_compressed_size_ = false;
131 current_compressed_size_ = 0;
132 compressed_bytes_consumed_ = 0;
133 ++current_header_id_;