Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / quic / quic_headers_stream.cc
1 // Copyright 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_headers_stream.h"
6
7 #include "net/quic/quic_session.h"
8
9 using base::StringPiece;
10
11 namespace net {
12
13 namespace {
14
15 const QuicStreamId kInvalidStreamId = 0;
16
17 }  // namespace
18
19 // A SpdyFramer visitor which passed SYN_STREAM and SYN_REPLY frames to
20 // the QuicDataStream, and closes the connection if any unexpected frames
21 // are received.
22 class QuicHeadersStream::SpdyFramerVisitor
23     : public SpdyFramerVisitorInterface,
24       public SpdyFramerDebugVisitorInterface {
25  public:
26   explicit SpdyFramerVisitor(QuicHeadersStream* stream) : stream_(stream) {}
27
28   // SpdyFramerVisitorInterface implementation
29   void OnSynStream(SpdyStreamId stream_id,
30                    SpdyStreamId associated_stream_id,
31                    SpdyPriority priority,
32                    bool fin,
33                    bool unidirectional) override {
34     if (!stream_->IsConnected()) {
35       return;
36     }
37
38     if (associated_stream_id != 0) {
39       CloseConnection("associated_stream_id != 0");
40       return;
41     }
42
43     if (unidirectional != 0) {
44       CloseConnection("unidirectional != 0");
45       return;
46     }
47
48     stream_->OnSynStream(stream_id, priority, fin);
49   }
50
51   void OnSynReply(SpdyStreamId stream_id, bool fin) override {
52     if (!stream_->IsConnected()) {
53       return;
54     }
55
56     stream_->OnSynReply(stream_id, fin);
57   }
58
59   bool OnControlFrameHeaderData(SpdyStreamId stream_id,
60                                 const char* header_data,
61                                 size_t len) override {
62     if (!stream_->IsConnected()) {
63       return false;
64     }
65     stream_->OnControlFrameHeaderData(stream_id, header_data, len);
66     return true;
67   }
68
69   void OnStreamFrameData(SpdyStreamId stream_id,
70                          const char* data,
71                          size_t len,
72                          bool fin) override {
73     if (fin && len == 0) {
74       // The framer invokes OnStreamFrameData with zero-length data and
75       // fin = true after processing a SYN_STREAM or SYN_REPLY frame
76       // that had the fin bit set.
77       return;
78     }
79     CloseConnection("SPDY DATA frame received.");
80   }
81
82   void OnError(SpdyFramer* framer) override {
83     CloseConnection("SPDY framing error.");
84   }
85
86   void OnDataFrameHeader(SpdyStreamId stream_id,
87                          size_t length,
88                          bool fin) override {
89     CloseConnection("SPDY DATA frame received.");
90   }
91
92   void OnRstStream(SpdyStreamId stream_id,
93                    SpdyRstStreamStatus status) override {
94     CloseConnection("SPDY RST_STREAM frame received.");
95   }
96
97   void OnSetting(SpdySettingsIds id, uint8 flags, uint32 value) override {
98     CloseConnection("SPDY SETTINGS frame received.");
99   }
100
101   void OnSettingsAck() override {
102     CloseConnection("SPDY SETTINGS frame received.");
103   }
104
105   void OnSettingsEnd() override {
106     CloseConnection("SPDY SETTINGS frame received.");
107   }
108
109   void OnPing(SpdyPingId unique_id, bool is_ack) override {
110     CloseConnection("SPDY PING frame received.");
111   }
112
113   void OnGoAway(SpdyStreamId last_accepted_stream_id,
114                 SpdyGoAwayStatus status) override {
115     CloseConnection("SPDY GOAWAY frame received.");
116   }
117
118   void OnHeaders(SpdyStreamId stream_id,
119                  bool has_priority,
120                  SpdyPriority priority,
121                  bool fin,
122                  bool end) override {
123     CloseConnection("SPDY HEADERS frame received.");
124   }
125
126   void OnWindowUpdate(SpdyStreamId stream_id,
127                       uint32 delta_window_size) override {
128     CloseConnection("SPDY WINDOW_UPDATE frame received.");
129   }
130
131   void OnPushPromise(SpdyStreamId stream_id,
132                      SpdyStreamId promised_stream_id,
133                      bool end) override {
134     LOG(DFATAL) << "PUSH_PROMISE frame received from a SPDY/3 framer";
135     CloseConnection("SPDY PUSH_PROMISE frame received.");
136   }
137
138   void OnContinuation(SpdyStreamId stream_id, bool end) override {
139     CloseConnection("SPDY CONTINUATION frame received.");
140   }
141
142   bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) override {
143     CloseConnection("SPDY unknown frame received.");
144     return false;
145   }
146
147   // SpdyFramerDebugVisitorInterface implementation
148   void OnSendCompressedFrame(SpdyStreamId stream_id,
149                              SpdyFrameType type,
150                              size_t payload_len,
151                              size_t frame_len) override {}
152
153   void OnReceiveCompressedFrame(SpdyStreamId stream_id,
154                                 SpdyFrameType type,
155                                 size_t frame_len) override {
156     if (stream_->IsConnected()) {
157       stream_->OnCompressedFrameSize(frame_len);
158     }
159   }
160
161  private:
162   void CloseConnection(const string& details) {
163     if (stream_->IsConnected()) {
164       stream_->CloseConnectionWithDetails(
165           QUIC_INVALID_HEADERS_STREAM_DATA, details);
166     }
167   }
168
169  private:
170   QuicHeadersStream* stream_;
171
172   DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor);
173 };
174
175 QuicHeadersStream::QuicHeadersStream(QuicSession* session)
176     : ReliableQuicStream(kHeadersStreamId, session),
177       stream_id_(kInvalidStreamId),
178       fin_(false),
179       frame_len_(0),
180       spdy_framer_(SPDY3),
181       spdy_framer_visitor_(new SpdyFramerVisitor(this)) {
182   spdy_framer_.set_visitor(spdy_framer_visitor_.get());
183   spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get());
184   if (version() < QUIC_VERSION_21) {
185     // Prior to QUIC_VERSION_21 the headers stream is not subject to any flow
186     // control.
187     DisableFlowControl();
188   }
189   // The headers stream is exempt from connection level flow control.
190   DisableConnectionFlowControlForThisStream();
191 }
192
193 QuicHeadersStream::~QuicHeadersStream() {}
194
195 size_t QuicHeadersStream::WriteHeaders(
196     QuicStreamId stream_id,
197     const SpdyHeaderBlock& headers,
198     bool fin,
199     QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
200   scoped_ptr<SpdySerializedFrame> frame;
201   if (session()->is_server()) {
202     SpdySynReplyIR syn_reply(stream_id);
203     syn_reply.set_name_value_block(headers);
204     syn_reply.set_fin(fin);
205     frame.reset(spdy_framer_.SerializeFrame(syn_reply));
206   } else {
207     SpdySynStreamIR syn_stream(stream_id);
208     syn_stream.set_name_value_block(headers);
209     syn_stream.set_fin(fin);
210     frame.reset(spdy_framer_.SerializeFrame(syn_stream));
211   }
212   WriteOrBufferData(StringPiece(frame->data(), frame->size()), false,
213                     ack_notifier_delegate);
214   return frame->size();
215 }
216
217 uint32 QuicHeadersStream::ProcessRawData(const char* data,
218                                          uint32 data_len) {
219   return spdy_framer_.ProcessInput(data, data_len);
220 }
221
222 QuicPriority QuicHeadersStream::EffectivePriority() const { return 0; }
223
224 void QuicHeadersStream::OnSynStream(SpdyStreamId stream_id,
225                                     SpdyPriority priority,
226                                     bool fin) {
227   if (!session()->is_server()) {
228     CloseConnectionWithDetails(
229         QUIC_INVALID_HEADERS_STREAM_DATA,
230         "SPDY SYN_STREAM frame received at the client");
231     return;
232   }
233   DCHECK_EQ(kInvalidStreamId, stream_id_);
234   stream_id_ = stream_id;
235   fin_ = fin;
236   session()->OnStreamHeadersPriority(stream_id, priority);
237 }
238
239 void QuicHeadersStream::OnSynReply(SpdyStreamId stream_id, bool fin) {
240   if (session()->is_server()) {
241     CloseConnectionWithDetails(
242         QUIC_INVALID_HEADERS_STREAM_DATA,
243         "SPDY SYN_REPLY frame received at the server");
244     return;
245   }
246   DCHECK_EQ(kInvalidStreamId, stream_id_);
247   stream_id_ = stream_id;
248   fin_ = fin;
249 }
250
251 void QuicHeadersStream::OnControlFrameHeaderData(SpdyStreamId stream_id,
252                                                  const char* header_data,
253                                                  size_t len) {
254   DCHECK_EQ(stream_id_, stream_id);
255   if (len == 0) {
256     DCHECK_NE(0u, stream_id_);
257     DCHECK_NE(0u, frame_len_);
258     session()->OnStreamHeadersComplete(stream_id_, fin_, frame_len_);
259     // Reset state for the next frame.
260     stream_id_ = kInvalidStreamId;
261     fin_ = false;
262     frame_len_ = 0;
263   } else {
264     session()->OnStreamHeaders(stream_id_, StringPiece(header_data, len));
265   }
266 }
267
268 void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) {
269   DCHECK_EQ(kInvalidStreamId, stream_id_);
270   DCHECK_EQ(0u, frame_len_);
271   frame_len_ = frame_len;
272 }
273
274 bool QuicHeadersStream::IsConnected() {
275   return session()->connection()->connected();
276 }
277
278 }  // namespace net