Upstream version 10.39.225.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   virtual 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   virtual 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   virtual 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   virtual 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   virtual void OnError(SpdyFramer* framer) OVERRIDE {
83     CloseConnection("SPDY framing error.");
84   }
85
86   virtual void OnDataFrameHeader(SpdyStreamId stream_id,
87                                  size_t length,
88                                  bool fin) OVERRIDE {
89     CloseConnection("SPDY DATA frame received.");
90   }
91
92   virtual void OnRstStream(SpdyStreamId stream_id,
93                            SpdyRstStreamStatus status) OVERRIDE {
94     CloseConnection("SPDY RST_STREAM frame received.");
95   }
96
97   virtual void OnSetting(SpdySettingsIds id,
98                          uint8 flags,
99                          uint32 value) OVERRIDE {
100     CloseConnection("SPDY SETTINGS frame received.");
101   }
102
103   virtual void OnSettingsAck() OVERRIDE {
104     CloseConnection("SPDY SETTINGS frame received.");
105   }
106
107   virtual void OnSettingsEnd() OVERRIDE {
108     CloseConnection("SPDY SETTINGS frame received.");
109   }
110
111   virtual void OnPing(SpdyPingId unique_id, bool is_ack) OVERRIDE {
112     CloseConnection("SPDY PING frame received.");
113   }
114
115   virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
116                         SpdyGoAwayStatus status) OVERRIDE {
117     CloseConnection("SPDY GOAWAY frame received.");
118   }
119
120   virtual void OnHeaders(SpdyStreamId stream_id, bool fin, bool end) OVERRIDE {
121     CloseConnection("SPDY HEADERS frame received.");
122   }
123
124   virtual void OnWindowUpdate(SpdyStreamId stream_id,
125                               uint32 delta_window_size) OVERRIDE {
126     CloseConnection("SPDY WINDOW_UPDATE frame received.");
127   }
128
129   virtual void OnPushPromise(SpdyStreamId stream_id,
130                              SpdyStreamId promised_stream_id,
131                              bool end) OVERRIDE {
132     LOG(DFATAL) << "PUSH_PROMISE frame received from a SPDY/3 framer";
133     CloseConnection("SPDY PUSH_PROMISE frame received.");
134   }
135
136   virtual void OnContinuation(SpdyStreamId stream_id, bool end) OVERRIDE {
137     CloseConnection("SPDY CONTINUATION frame received.");
138   }
139
140   virtual bool OnUnknownFrame(SpdyStreamId stream_id, int frame_type) OVERRIDE {
141     CloseConnection("SPDY unknown frame received.");
142     return false;
143   }
144
145   // SpdyFramerDebugVisitorInterface implementation
146   virtual void OnSendCompressedFrame(SpdyStreamId stream_id,
147                                      SpdyFrameType type,
148                                      size_t payload_len,
149                                      size_t frame_len) OVERRIDE {}
150
151   virtual void OnReceiveCompressedFrame(SpdyStreamId stream_id,
152                                         SpdyFrameType type,
153                                         size_t frame_len) OVERRIDE {
154     if (stream_->IsConnected()) {
155       stream_->OnCompressedFrameSize(frame_len);
156     }
157   }
158
159  private:
160   void CloseConnection(const string& details) {
161     if (stream_->IsConnected()) {
162       stream_->CloseConnectionWithDetails(
163           QUIC_INVALID_HEADERS_STREAM_DATA, details);
164     }
165   }
166
167  private:
168   QuicHeadersStream* stream_;
169
170   DISALLOW_COPY_AND_ASSIGN(SpdyFramerVisitor);
171 };
172
173 QuicHeadersStream::QuicHeadersStream(QuicSession* session)
174     : ReliableQuicStream(kHeadersStreamId, session),
175       stream_id_(kInvalidStreamId),
176       fin_(false),
177       frame_len_(0),
178       spdy_framer_(SPDY3),
179       spdy_framer_visitor_(new SpdyFramerVisitor(this)) {
180   spdy_framer_.set_visitor(spdy_framer_visitor_.get());
181   spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get());
182   if (version() < QUIC_VERSION_21) {
183     // Prior to QUIC_VERSION_21 the headers stream is not subject to any flow
184     // control.
185     DisableFlowControl();
186   }
187   // The headers stream is exempt from connection level flow control.
188   DisableConnectionFlowControlForThisStream();
189 }
190
191 QuicHeadersStream::~QuicHeadersStream() {}
192
193 size_t QuicHeadersStream::WriteHeaders(
194     QuicStreamId stream_id,
195     const SpdyHeaderBlock& headers,
196     bool fin,
197     QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
198   scoped_ptr<SpdySerializedFrame> frame;
199   if (session()->is_server()) {
200     SpdySynReplyIR syn_reply(stream_id);
201     syn_reply.set_name_value_block(headers);
202     syn_reply.set_fin(fin);
203     frame.reset(spdy_framer_.SerializeFrame(syn_reply));
204   } else {
205     SpdySynStreamIR syn_stream(stream_id);
206     syn_stream.set_name_value_block(headers);
207     syn_stream.set_fin(fin);
208     frame.reset(spdy_framer_.SerializeFrame(syn_stream));
209   }
210   WriteOrBufferData(StringPiece(frame->data(), frame->size()), false,
211                     ack_notifier_delegate);
212   return frame->size();
213 }
214
215 uint32 QuicHeadersStream::ProcessRawData(const char* data,
216                                          uint32 data_len) {
217   return spdy_framer_.ProcessInput(data, data_len);
218 }
219
220 QuicPriority QuicHeadersStream::EffectivePriority() const { return 0; }
221
222 void QuicHeadersStream::OnSynStream(SpdyStreamId stream_id,
223                                     SpdyPriority priority,
224                                     bool fin) {
225   if (!session()->is_server()) {
226     CloseConnectionWithDetails(
227         QUIC_INVALID_HEADERS_STREAM_DATA,
228         "SPDY SYN_STREAM frame received at the client");
229     return;
230   }
231   DCHECK_EQ(kInvalidStreamId, stream_id_);
232   stream_id_ = stream_id;
233   fin_ = fin;
234   session()->OnStreamHeadersPriority(stream_id, priority);
235 }
236
237 void QuicHeadersStream::OnSynReply(SpdyStreamId stream_id, bool fin) {
238   if (session()->is_server()) {
239     CloseConnectionWithDetails(
240         QUIC_INVALID_HEADERS_STREAM_DATA,
241         "SPDY SYN_REPLY frame received at the server");
242     return;
243   }
244   DCHECK_EQ(kInvalidStreamId, stream_id_);
245   stream_id_ = stream_id;
246   fin_ = fin;
247 }
248
249 void QuicHeadersStream::OnControlFrameHeaderData(SpdyStreamId stream_id,
250                                                  const char* header_data,
251                                                  size_t len) {
252   DCHECK_EQ(stream_id_, stream_id);
253   if (len == 0) {
254     DCHECK_NE(0u, stream_id_);
255     DCHECK_NE(0u, frame_len_);
256     session()->OnStreamHeadersComplete(stream_id_, fin_, frame_len_);
257     // Reset state for the next frame.
258     stream_id_ = kInvalidStreamId;
259     fin_ = false;
260     frame_len_ = 0;
261   } else {
262     session()->OnStreamHeaders(stream_id_, StringPiece(header_data, len));
263   }
264 }
265
266 void QuicHeadersStream::OnCompressedFrameSize(size_t frame_len) {
267   DCHECK_EQ(kInvalidStreamId, stream_id_);
268   DCHECK_EQ(0u, frame_len_);
269   frame_len_ = frame_len;
270 }
271
272 bool QuicHeadersStream::IsConnected() {
273   return session()->connection()->connected();
274 }
275
276 }  // namespace net