- add sources.
[platform/framework/web/crosswalk.git] / src / net / quic / quic_spdy_decompressor.cc
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.
4
5 #include "net/quic/quic_spdy_decompressor.h"
6
7 #include <algorithm>
8
9 #include "base/logging.h"
10
11 using base::StringPiece;
12 using std::min;
13
14 namespace net {
15
16 class SpdyFramerVisitor : public SpdyFramerVisitorInterface {
17  public:
18   explicit SpdyFramerVisitor(QuicSpdyDecompressor::Visitor* visitor)
19       : visitor_(visitor),
20         error_(false) {
21   }
22
23   virtual void OnError(SpdyFramer* framer) OVERRIDE {
24     error_ = true;
25   }
26   virtual void OnDataFrameHeader(SpdyStreamId stream_id,
27                                  size_t length,
28                                  bool fin) OVERRIDE {}
29   virtual void OnStreamFrameData(SpdyStreamId stream_id,
30                                  const char* data,
31                                  size_t len,
32                                  bool fin) OVERRIDE {}
33   virtual bool OnControlFrameHeaderData(SpdyStreamId stream_id,
34                                         const char* header_data,
35                                         size_t len) OVERRIDE;
36   virtual void OnSynStream(SpdyStreamId stream_id,
37                            SpdyStreamId associated_stream_id,
38                            SpdyPriority priority,
39                            uint8 credential_slot,
40                            bool fin,
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,
46                          uint8 flags,
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 {
56     return false;
57   }
58   virtual void OnPushPromise(SpdyStreamId stream_id,
59                              SpdyStreamId promised_stream_id) OVERRIDE {}
60   void set_visitor(QuicSpdyDecompressor::Visitor* visitor) {
61     DCHECK(visitor);
62     visitor_ = visitor;
63   }
64
65  private:
66   QuicSpdyDecompressor::Visitor* visitor_;
67   bool error_;
68 };
69
70 bool SpdyFramerVisitor::OnControlFrameHeaderData(SpdyStreamId stream_id,
71                                                  const char* header_data,
72                                                  size_t len) {
73   DCHECK(visitor_);
74   return visitor_->OnDecompressedData(StringPiece(header_data, len));
75 }
76
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());
85 }
86
87 QuicSpdyDecompressor::~QuicSpdyDecompressor() {
88 }
89
90 size_t QuicSpdyDecompressor::DecompressData(StringPiece data,
91                                             Visitor* visitor) {
92   spdy_visitor_->set_visitor(visitor);
93   size_t bytes_consumed = 0;
94
95   if (!has_current_compressed_size_) {
96     const size_t kCompressedBufferSizeSize = sizeof(uint32);
97     DCHECK_GT(kCompressedBufferSizeSize, compressed_size_buffer_.length());
98     size_t missing_size =
99         kCompressedBufferSizeSize - compressed_size_buffer_.length();
100     if (data.length() < missing_size) {
101       data.AppendToString(&compressed_size_buffer_);
102       return data.length();
103     }
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(&current_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;
113   }
114
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;
123     }
124     compressed_bytes_consumed_ += bytes_to_consume;
125     bytes_consumed += bytes_to_consume;
126   }
127   if (current_compressed_size_ - compressed_bytes_consumed_ == 0) {
128     ResetForNextHeaders();
129   }
130   return bytes_consumed;
131 }
132
133 void QuicSpdyDecompressor::ResetForNextHeaders() {
134   has_current_compressed_size_ = false;
135   current_compressed_size_ = 0;
136   compressed_bytes_consumed_ = 0;
137   ++current_header_id_;
138 }
139
140 }  // namespace net