1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_test_util.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/basictypes.h"
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
1272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/http/http_network_session.h"
133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/http/http_network_transaction.h"
143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/spdy/spdy_framer.h"
1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/spdy/spdy_http_utils.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net {
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Chop a frame into an array of MockWrites.
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |data| is the frame to chop.
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |length| is the length of the frame to chop.
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |num_chunks| is the number of chunks to create.
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMockWrite* ChopWriteFrame(const char* data, int length, int num_chunks) {
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockWrite* chunks = new MockWrite[num_chunks];
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int chunk_size = length / num_chunks;
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int index = 0; index < num_chunks; index++) {
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* ptr = data + (index * chunk_size);
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (index == num_chunks - 1)
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      chunk_size += length % chunk_size;  // The last chunk takes the remainder.
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    chunks[index] = MockWrite(true, ptr, chunk_size);
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return chunks;
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Chop a SpdyFrame into an array of MockWrites.
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |frame| is the frame to chop.
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |num_chunks| is the number of chunks to create.
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMockWrite* ChopWriteFrame(const spdy::SpdyFrame& frame, int num_chunks) {
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return ChopWriteFrame(frame.data(),
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        frame.length() + spdy::SpdyFrame::size(),
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        num_chunks);
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Chop a frame into an array of MockReads.
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |data| is the frame to chop.
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |length| is the length of the frame to chop.
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |num_chunks| is the number of chunks to create.
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMockRead* ChopReadFrame(const char* data, int length, int num_chunks) {
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MockRead* chunks = new MockRead[num_chunks];
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int chunk_size = length / num_chunks;
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int index = 0; index < num_chunks; index++) {
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* ptr = data + (index * chunk_size);
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (index == num_chunks - 1)
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      chunk_size += length % chunk_size;  // The last chunk takes the remainder.
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    chunks[index] = MockRead(true, ptr, chunk_size);
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return chunks;
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Chop a SpdyFrame into an array of MockReads.
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |frame| is the frame to chop.
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |num_chunks| is the number of chunks to create.
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMockRead* ChopReadFrame(const spdy::SpdyFrame& frame, int num_chunks) {
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return ChopReadFrame(frame.data(),
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       frame.length() + spdy::SpdyFrame::size(),
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       num_chunks);
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Adds headers and values to a map.
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |extra_headers| is an array of { name, value } pairs, arranged as strings
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// where the even entries are the header names, and the odd entries are the
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// header values.
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |headers| gets filled in from |extra_headers|.
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AppendHeadersToSpdyFrame(const char* const extra_headers[],
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              int extra_header_count,
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              spdy::SpdyHeaderBlock* headers) {
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string this_header;
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string this_value;
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!extra_header_count)
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Sanity check: Non-NULL header list.
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(NULL != extra_headers) << "NULL header value pair list";
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Sanity check: Non-NULL header map.
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(NULL != headers) << "NULL header map";
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Copy in the headers.
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = 0; i < extra_header_count; i++) {
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Sanity check: Non-empty header.
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK_NE('\0', *extra_headers[i * 2]) << "Empty header value pair";
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    this_header = extra_headers[i * 2];
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string::size_type header_len = this_header.length();
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!header_len)
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      continue;
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    this_value = extra_headers[1 + (i * 2)];
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string new_value;
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (headers->find(this_header) != headers->end()) {
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // More than one entry in the header.
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Don't add the header again, just the append to the value,
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // separated by a NULL character.
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Adjust the value.
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new_value = (*headers)[this_header];
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Put in a NULL separator.
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new_value.append(1, '\0');
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Append the new value.
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new_value += this_value;
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Not a duplicate, just write the value.
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new_value = this_value;
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    (*headers)[this_header] = new_value;
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Writes |val| to a location of size |len|, in big-endian format.
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// in the buffer pointed to by |buffer_handle|.
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Updates the |*buffer_handle| pointer by |len|
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns the number of bytes written
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint AppendToBuffer(int val,
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   int len,
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   unsigned char** buffer_handle,
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   int* buffer_len_remaining) {
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (len <= 0)
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK((size_t) len <= sizeof(len)) << "Data length too long for data type";
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(NULL != buffer_handle) << "NULL buffer handle";
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(NULL != *buffer_handle) << "NULL pointer";
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(NULL != buffer_len_remaining)
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      << "NULL buffer remainder length pointer";
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_GE(*buffer_len_remaining, len) << "Insufficient buffer size";
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = 0; i < len; i++) {
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int shift = (8 * (len - (i + 1)));
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    unsigned char val_chunk = (val >> shift) & 0x0FF;
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *(*buffer_handle)++ = val_chunk;
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    *buffer_len_remaining += 1;
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return len;
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Construct a SPDY packet.
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |head| is the start of the packet, up to but not including
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the header value pairs.
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |extra_headers| are the extra header-value pairs, which typically
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// will vary the most between calls.
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |tail| is any (relatively constant) header-value pairs to add.
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |buffer| is the buffer we're filling in.
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns a SpdyFrame.
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy::SpdyFrame* ConstructSpdyPacket(const SpdyHeaderInfo& header_info,
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     const char* const extra_headers[],
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     int extra_header_count,
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     const char* const tail[],
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     int tail_header_count) {
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyFramer framer;
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyHeaderBlock headers;
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Copy in the extra headers to our map.
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AppendHeadersToSpdyFrame(extra_headers, extra_header_count, &headers);
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Copy in the tail headers to our map.
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (tail && tail_header_count)
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AppendHeadersToSpdyFrame(tail, tail_header_count, &headers);
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyFrame* frame = NULL;
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (header_info.kind) {
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case spdy::SYN_STREAM:
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      frame = framer.CreateSynStream(header_info.id, header_info.assoc_id,
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     header_info.priority,
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     header_info.control_flags,
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     header_info.compressed, &headers);
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case spdy::SYN_REPLY:
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      frame = framer.CreateSynReply(header_info.id, header_info.control_flags,
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    header_info.compressed, &headers);
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case spdy::RST_STREAM:
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      frame = framer.CreateRstStream(header_info.id, header_info.status);
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
176201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    case spdy::HEADERS:
177201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      frame = framer.CreateHeaders(header_info.id, header_info.control_flags,
178201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   header_info.compressed, &headers);
179201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      break;
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      frame = framer.CreateDataFrame(header_info.id, header_info.data,
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     header_info.data_length,
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     header_info.data_flags);
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return frame;
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Construct an expected SPDY SETTINGS frame.
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |settings| are the settings to set.
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns the constructed frame.  The caller takes ownership of the frame.
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy::SpdyFrame* ConstructSpdySettings(spdy::SpdySettings settings) {
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyFramer framer;
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return framer.CreateSettings(settings);
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1972c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun// Construct a SPDY PING frame.
1982c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun// Returns the constructed frame.  The caller takes ownership of the frame.
1992c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunspdy::SpdyFrame* ConstructSpdyPing() {
2002c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun  spdy::SpdyFramer framer;
2012c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun  return framer.CreatePingFrame(1);
2022c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun}
2032c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Construct a SPDY GOAWAY frame.
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns the constructed frame.  The caller takes ownership of the frame.
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy::SpdyFrame* ConstructSpdyGoAway() {
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyFramer framer;
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return framer.CreateGoAway(0);
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Construct a SPDY WINDOW_UPDATE frame.
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns the constructed frame.  The caller takes ownership of the frame.
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy::SpdyFrame* ConstructSpdyWindowUpdate(
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const spdy::SpdyStreamId stream_id, uint32 delta_window_size) {
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyFramer framer;
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return framer.CreateWindowUpdate(stream_id, delta_window_size);
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Construct a SPDY RST_STREAM frame.
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns the constructed frame.  The caller takes ownership of the frame.
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy::SpdyFrame* ConstructSpdyRstStream(spdy::SpdyStreamId stream_id,
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        spdy::SpdyStatusCodes status) {
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyFramer framer;
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return framer.CreateRstStream(stream_id, status);
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Construct a single SPDY header entry, for validation.
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |extra_headers| are the extra header-value pairs.
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |buffer| is the buffer we're filling in.
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |index| is the index of the header we want.
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns the number of bytes written into |buffer|.
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint ConstructSpdyHeader(const char* const extra_headers[],
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        int extra_header_count,
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        char* buffer,
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        int buffer_length,
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        int index) {
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* this_header = NULL;
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* this_value = NULL;
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!buffer || !buffer_length)
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *buffer = '\0';
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Sanity check: Non-empty header list.
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(NULL != extra_headers) << "NULL extra headers pointer";
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Sanity check: Index out of range.
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK((index >= 0) && (index < extra_header_count))
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      << "Index " << index
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      << " out of range [0, " << extra_header_count << ")";
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  this_header = extra_headers[index * 2];
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Sanity check: Non-empty header.
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!*this_header)
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string::size_type header_len = strlen(this_header);
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!header_len)
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  this_value = extra_headers[1 + (index * 2)];
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Sanity check: Non-empty value.
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!*this_value)
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    this_value = "";
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int n = base::snprintf(buffer,
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         buffer_length,
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         "%s: %s\r\n",
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         this_header,
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         this_value);
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return n;
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickspdy::SpdyFrame* ConstructSpdyControlFrame(const char* const extra_headers[],
2683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           int extra_header_count,
2693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           bool compressed,
2703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           int stream_id,
2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           RequestPriority request_priority,
2723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           spdy::SpdyControlType type,
2733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           spdy::SpdyControlFlags flags,
2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           const char* const* kHeaders,
2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           int kHeadersSize) {
2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return ConstructSpdyControlFrame(extra_headers,
2773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   extra_header_count,
2783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   compressed,
2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   stream_id,
2803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   request_priority,
2813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   type,
2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   flags,
2833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   kHeaders,
2843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   kHeadersSize,
2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   0);
2863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickspdy::SpdyFrame* ConstructSpdyControlFrame(const char* const extra_headers[],
2893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           int extra_header_count,
2903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           bool compressed,
2913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           int stream_id,
2923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           RequestPriority request_priority,
2933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           spdy::SpdyControlType type,
2943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           spdy::SpdyControlFlags flags,
2953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           const char* const* kHeaders,
2963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           int kHeadersSize,
2973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                           int associated_stream_id) {
2983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const SpdyHeaderInfo kSynStartHeader = {
2993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    type,                         // Kind = Syn
3003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    stream_id,                    // Stream ID
3013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    associated_stream_id,         // Associated stream ID
30272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ConvertRequestPriorityToSpdyPriority(request_priority),
3033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  // Priority
3043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    flags,                        // Control Flags
3053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    compressed,                   // Compressed
3063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::INVALID,                // Status
3073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NULL,                         // Data
3083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Length
3093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::DATA_FLAG_NONE          // Data Flags
3103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
3113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return ConstructSpdyPacket(kSynStartHeader,
3123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             extra_headers,
3133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             extra_header_count,
3143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             kHeaders,
3153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             kHeadersSize / 2);
3163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
3173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Constructs a standard SPDY GET SYN packet, optionally compressed
3193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// for the url |url|.
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |extra_headers| are the extra header-value pairs, which typically
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// will vary the most between calls.
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns a SpdyFrame.
3233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickspdy::SpdyFrame* ConstructSpdyGet(const char* const url,
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  bool compressed,
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  int stream_id,
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  RequestPriority request_priority) {
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const SpdyHeaderInfo kSynStartHeader = {
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::SYN_STREAM,             // Kind = Syn
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    stream_id,                    // Stream ID
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,                            // Associated stream ID
3313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    net::ConvertRequestPriorityToSpdyPriority(request_priority),
3323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  // Priority
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::CONTROL_FLAG_FIN,       // Control Flags
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    compressed,                   // Compressed
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::INVALID,                // Status
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NULL,                         // Data
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    0,                            // Length
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    spdy::DATA_FLAG_NONE          // Data Flags
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
3403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  GURL gurl(url);
3423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // This is so ugly.  Why are we using char* in here again?
3443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string str_path = gurl.PathForRequest();
3453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string str_scheme = gurl.scheme();
346201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::string str_host = gurl.host();
347201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (gurl.has_port()) {
348201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    str_host += ":";
349201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    str_host += gurl.port();
350201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
3513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_array<char> req(new char[str_path.size() + 1]);
3523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_array<char> scheme(new char[str_scheme.size() + 1]);
3533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scoped_array<char> host(new char[str_host.size() + 1]);
3543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  memcpy(req.get(), str_path.c_str(), str_path.size());
3553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  memcpy(scheme.get(), str_scheme.c_str(), str_scheme.size());
3563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  memcpy(host.get(), str_host.c_str(), str_host.size());
3573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  req.get()[str_path.size()] = '\0';
3583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  scheme.get()[str_scheme.size()] = '\0';
3593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  host.get()[str_host.size()] = '\0';
3603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const headers[] = {
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "method",
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "GET",
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "url",
3653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    req.get(),
3663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "host",
3673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    host.get(),
3683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "scheme",
3693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    scheme.get(),
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "version",
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "HTTP/1.1"
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return ConstructSpdyPacket(
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      kSynStartHeader,
3753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NULL,
3763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      0,
3773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      headers,
3783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      arraysize(headers) / 2);
3793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
3803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Constructs a standard SPDY GET SYN packet, optionally compressed.
3823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// |extra_headers| are the extra header-value pairs, which typically
3833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// will vary the most between calls.
3843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Returns a SpdyFrame.
3853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickspdy::SpdyFrame* ConstructSpdyGet(const char* const extra_headers[],
3863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  int extra_header_count,
3873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  bool compressed,
3883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  int stream_id,
3893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  RequestPriority request_priority) {
3903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return ConstructSpdyGet(extra_headers, extra_header_count, compressed,
3913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          stream_id, request_priority, true);
3923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
3933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Constructs a standard SPDY GET SYN packet, optionally compressed.
3953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// |extra_headers| are the extra header-value pairs, which typically
3963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// will vary the most between calls.
3973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Returns a SpdyFrame.
3983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickspdy::SpdyFrame* ConstructSpdyGet(const char* const extra_headers[],
3993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  int extra_header_count,
4003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  bool compressed,
4013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  int stream_id,
4023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  RequestPriority request_priority,
4033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  bool direct) {
4043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kStandardGetHeaders[] = {
4053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "method",
4063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "GET",
4073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "url",
4083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    (direct ? "/" : "http://www.google.com/"),
4093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "host",
4103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "www.google.com",
4113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "scheme",
4123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "http",
4133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version",
4143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "HTTP/1.1"
4153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
4163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return ConstructSpdyControlFrame(extra_headers,
4173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   extra_header_count,
4183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   compressed,
4193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   stream_id,
4203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   request_priority,
4213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   spdy::SYN_STREAM,
4223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   spdy::CONTROL_FLAG_FIN,
4233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   kStandardGetHeaders,
4243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   arraysize(kStandardGetHeaders));
4253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
4263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
427731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Constructs a standard SPDY SYN_STREAM frame for a CONNECT request.
428731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickspdy::SpdyFrame* ConstructSpdyConnect(const char* const extra_headers[],
429731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                      int extra_header_count,
430731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                      int stream_id) {
431731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const char* const kConnectHeaders[] = {
432731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    "method", "CONNECT",
433731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    "url", "www.google.com:443",
434731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    "host", "www.google.com",
435731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    "version", "HTTP/1.1",
436731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  };
437731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return ConstructSpdyControlFrame(extra_headers,
438731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                   extra_header_count,
439731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                   /*compressed*/ false,
440731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                   stream_id,
441731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                   LOWEST,
442731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                   spdy::SYN_STREAM,
443731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                   spdy::CONTROL_FLAG_NONE,
444731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                   kConnectHeaders,
445731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                   arraysize(kConnectHeaders));
446731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
447731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
4483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Constructs a standard SPDY push SYN packet.
4493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// |extra_headers| are the extra header-value pairs, which typically
4503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// will vary the most between calls.
4513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Returns a SpdyFrame.
4523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickspdy::SpdyFrame* ConstructSpdyPush(const char* const extra_headers[],
4533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   int extra_header_count,
4543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   int stream_id,
4553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   int associated_stream_id) {
4563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kStandardGetHeaders[] = {
4573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "hello",
4583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "bye",
4593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "status",
4603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "200",
4613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version",
4623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "HTTP/1.1"
4633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
4643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return ConstructSpdyControlFrame(extra_headers,
4653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   extra_header_count,
4663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   false,
4673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   stream_id,
4683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   LOWEST,
4693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   spdy::SYN_STREAM,
4703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   spdy::CONTROL_FLAG_NONE,
4713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   kStandardGetHeaders,
4723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   arraysize(kStandardGetHeaders),
4733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   associated_stream_id);
4743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
4753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickspdy::SpdyFrame* ConstructSpdyPush(const char* const extra_headers[],
4773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   int extra_header_count,
4783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   int stream_id,
4793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   int associated_stream_id,
480201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   const char* url) {
4813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kStandardGetHeaders[] = {
4823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "hello",
4833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "bye",
4843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "status",
4853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "200 OK",
4863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "url",
487201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    url,
4883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version",
4893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "HTTP/1.1"
4903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
4913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return ConstructSpdyControlFrame(extra_headers,
4923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   extra_header_count,
4933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   false,
4943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   stream_id,
4953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   LOWEST,
4963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   spdy::SYN_STREAM,
4973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   spdy::CONTROL_FLAG_NONE,
4983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   kStandardGetHeaders,
4993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   arraysize(kStandardGetHeaders),
5003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   associated_stream_id);
5013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
5033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickspdy::SpdyFrame* ConstructSpdyPush(const char* const extra_headers[],
5043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   int extra_header_count,
5053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   int stream_id,
5063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   int associated_stream_id,
507201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   const char* url,
5083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   const char* status,
509201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   const char* location) {
5103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* const kStandardGetHeaders[] = {
5113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "hello",
5123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "bye",
5133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "status",
5143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    status,
5153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "location",
5163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    location,
5173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "url",
5183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    url,
5193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version",
5203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "HTTP/1.1"
5213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
5223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return ConstructSpdyControlFrame(extra_headers,
5233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   extra_header_count,
5243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   false,
5253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   stream_id,
5263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   LOWEST,
5273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   spdy::SYN_STREAM,
5283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   spdy::CONTROL_FLAG_NONE,
5293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   kStandardGetHeaders,
5303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   arraysize(kStandardGetHeaders),
5313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   associated_stream_id);
5323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
5333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
534201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochspdy::SpdyFrame* ConstructSpdyPush(int stream_id,
535201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                  int associated_stream_id,
536201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                  const char* url) {
537201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  const char* const kStandardGetHeaders[] = {
538201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "url",
539201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    url
540201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
541201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return ConstructSpdyControlFrame(0,
542201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   0,
543201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   false,
544201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   stream_id,
545201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   LOWEST,
546201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   spdy::SYN_STREAM,
547201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   spdy::CONTROL_FLAG_NONE,
548201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   kStandardGetHeaders,
549201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   arraysize(kStandardGetHeaders),
550201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   associated_stream_id);
551201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
552201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
553201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochspdy::SpdyFrame* ConstructSpdyPushHeaders(int stream_id,
554201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          const char* const extra_headers[],
555201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                          int extra_header_count) {
556201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  const char* const kStandardGetHeaders[] = {
557201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "status",
558201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "200 OK",
559201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "version",
560201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    "HTTP/1.1"
561201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
562201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return ConstructSpdyControlFrame(extra_headers,
563201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   extra_header_count,
564201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   false,
565201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   stream_id,
566201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   LOWEST,
567201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   spdy::HEADERS,
568201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   spdy::CONTROL_FLAG_NONE,
569201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   kStandardGetHeaders,
570201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                   arraysize(kStandardGetHeaders));
571201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
572201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
573513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Constructs a standard SPDY SYN_REPLY packet with the specified status code.
5743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Returns a SpdyFrame.
575513209b27ff55e2841eac0e4120199c23acce758Ben Murdochspdy::SpdyFrame* ConstructSpdySynReplyError(
576513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    const char* const status,
577513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    const char* const* const extra_headers,
578513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    int extra_header_count,
579513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    int stream_id) {
580513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const char* const kStandardGetHeaders[] = {
5813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "hello",
5823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "bye",
5833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "status",
584513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    status,
5853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "version",
5863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "HTTP/1.1"
5873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
588513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return ConstructSpdyControlFrame(extra_headers,
589513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                   extra_header_count,
5903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   false,
5913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   stream_id,
5923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   LOWEST,
5933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   spdy::SYN_REPLY,
5943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   spdy::CONTROL_FLAG_NONE,
5953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   kStandardGetHeaders,
5963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   arraysize(kStandardGetHeaders));
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
599513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Constructs a standard SPDY SYN_REPLY packet to match the SPDY GET.
600513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// |extra_headers| are the extra header-value pairs, which typically
601513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// will vary the most between calls.
602513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch// Returns a SpdyFrame.
603513209b27ff55e2841eac0e4120199c23acce758Ben Murdochspdy::SpdyFrame* ConstructSpdyGetSynReplyRedirect(int stream_id) {
604513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  static const char* const kExtraHeaders[] = {
605513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "location",
606513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    "http://www.foo.com/index.php",
607513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  };
608513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return ConstructSpdySynReplyError("301 Moved Permanently", kExtraHeaders,
609513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                    arraysize(kExtraHeaders)/2, stream_id);
610513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
611513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
612731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Constructs a standard SPDY SYN_REPLY packet with an Internal Server
613731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Error status code.
614731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Returns a SpdyFrame.
615731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickspdy::SpdyFrame* ConstructSpdySynReplyError(int stream_id) {
616513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return ConstructSpdySynReplyError("500 Internal Server Error", NULL, 0, 1);
617731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
618731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
619513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
620513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
621731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Constructs a standard SPDY SYN_REPLY packet to match the SPDY GET.
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |extra_headers| are the extra header-value pairs, which typically
624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// will vary the most between calls.
625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns a SpdyFrame.
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy::SpdyFrame* ConstructSpdyGetSynReply(const char* const extra_headers[],
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          int extra_header_count,
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          int stream_id) {
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char* const kStandardGetHeaders[] = {
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "hello",
631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "bye",
632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "status",
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "200",
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "version",
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "HTTP/1.1"
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
6373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return ConstructSpdyControlFrame(extra_headers,
6383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   extra_header_count,
6393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   false,
6403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   stream_id,
6413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   LOWEST,
6423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   spdy::SYN_REPLY,
6433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   spdy::CONTROL_FLAG_NONE,
6443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   kStandardGetHeaders,
6453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   arraysize(kStandardGetHeaders));
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Constructs a standard SPDY POST SYN packet.
6493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// |content_length| is the size of post data.
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |extra_headers| are the extra header-value pairs, which typically
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// will vary the most between calls.
652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns a SpdyFrame.
6533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickspdy::SpdyFrame* ConstructSpdyPost(int64 content_length,
6543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   const char* const extra_headers[],
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   int extra_header_count) {
6563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string length_str = base::Int64ToString(content_length);
6573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const char* post_headers[] = {
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "method",
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "POST",
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "url",
6613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "/",
6623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "host",
6633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "www.google.com",
6643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "scheme",
6653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "http",
666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "version",
6673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "HTTP/1.1",
6683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "content-length",
6693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    length_str.c_str()
670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
6713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return ConstructSpdyControlFrame(extra_headers,
6723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   extra_header_count,
6733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   false,
6743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   1,
6753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   LOWEST,
6763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   spdy::SYN_STREAM,
6773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   spdy::CONTROL_FLAG_NONE,
6783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   post_headers,
6793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   arraysize(post_headers));
680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
682dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Constructs a chunked transfer SPDY POST SYN packet.
683dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// |extra_headers| are the extra header-value pairs, which typically
684dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// will vary the most between calls.
685dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Returns a SpdyFrame.
686dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenspdy::SpdyFrame* ConstructChunkedSpdyPost(const char* const extra_headers[],
687dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                          int extra_header_count) {
688dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const char* post_headers[] = {
689dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    "method",
690dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    "POST",
691dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    "url",
692dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    "/",
693dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    "host",
694dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    "www.google.com",
695dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    "scheme",
696dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    "http",
697dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    "version",
698dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    "HTTP/1.1"
699dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  };
700dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return ConstructSpdyControlFrame(extra_headers,
701dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                   extra_header_count,
702dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                   false,
703dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                   1,
704dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                   LOWEST,
705dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                   spdy::SYN_STREAM,
706dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                   spdy::CONTROL_FLAG_NONE,
707dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                   post_headers,
708dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                   arraysize(post_headers));
709dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
710dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Constructs a standard SPDY SYN_REPLY packet to match the SPDY POST.
712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |extra_headers| are the extra header-value pairs, which typically
713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// will vary the most between calls.
714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns a SpdyFrame.
715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy::SpdyFrame* ConstructSpdyPostSynReply(const char* const extra_headers[],
716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           int extra_header_count) {
717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const char* const kStandardGetHeaders[] = {
718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "hello",
719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "bye",
720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "status",
721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "200",
722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "url",
723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "/index.php",
724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "version",
725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "HTTP/1.1"
726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
7273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return ConstructSpdyControlFrame(extra_headers,
7283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   extra_header_count,
7293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   false,
7303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   1,
7313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   LOWEST,
7323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   spdy::SYN_REPLY,
7333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   spdy::CONTROL_FLAG_NONE,
7343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   kStandardGetHeaders,
7353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                   arraysize(kStandardGetHeaders));
736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Constructs a single SPDY data frame with the default contents.
739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochspdy::SpdyFrame* ConstructSpdyBodyFrame(int stream_id, bool fin) {
740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyFramer framer;
7413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return framer.CreateDataFrame(
7423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream_id, kUploadData, kUploadDataSize,
7433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      fin ? spdy::DATA_FLAG_FIN : spdy::DATA_FLAG_NONE);
7443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
7453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
7463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Constructs a single SPDY data frame with the given content.
7473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickspdy::SpdyFrame* ConstructSpdyBodyFrame(int stream_id, const char* data,
7483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                        uint32 len, bool fin) {
7493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  spdy::SpdyFramer framer;
7503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return framer.CreateDataFrame(
7513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      stream_id, data, len, fin ? spdy::DATA_FLAG_FIN : spdy::DATA_FLAG_NONE);
752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
754731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Wraps |frame| in the payload of a data frame in stream |stream_id|.
755731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickspdy::SpdyFrame* ConstructWrappedSpdyFrame(
756731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const scoped_ptr<spdy::SpdyFrame>& frame,
757731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    int stream_id) {
758731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return ConstructSpdyBodyFrame(stream_id, frame->data(),
759731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                frame->length() + spdy::SpdyFrame::size(),
760731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                false);
761731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
762731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Construct an expected SPDY reply string.
764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |extra_headers| are the extra header-value pairs, which typically
765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// will vary the most between calls.
766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// |buffer| is the buffer we're filling in.
767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns the number of bytes written into |buffer|.
768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint ConstructSpdyReplyString(const char* const extra_headers[],
769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             int extra_header_count,
770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             char* buffer,
771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             int buffer_length) {
772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int packet_size = 0;
773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int header_count = 0;
774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char* buffer_write = buffer;
775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int buffer_left = buffer_length;
776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyHeaderBlock headers;
777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!buffer || !buffer_length)
778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0;
779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Copy in the extra headers.
780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AppendHeadersToSpdyFrame(extra_headers, extra_header_count, &headers);
781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  header_count = headers.size();
782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The iterator gets us the list of header/value pairs in sorted order.
783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyHeaderBlock::iterator next = headers.begin();
784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  spdy::SpdyHeaderBlock::iterator last = headers.end();
785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for ( ; next != last; ++next) {
786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Write the header.
787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int value_len, current_len, offset;
788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* header_string = next->first.c_str();
789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    packet_size += AppendToBuffer(header_string,
790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  next->first.length(),
791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  &buffer_write,
792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  &buffer_left);
793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    packet_size += AppendToBuffer(": ",
794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  strlen(": "),
795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  &buffer_write,
796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  &buffer_left);
797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Write the value(s).
798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const char* value_string = next->second.c_str();
799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Check if it's split among two or more values.
800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    value_len = next->second.length();
801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    current_len = strlen(value_string);
802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    offset = 0;
803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Handle the first N-1 values.
804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    while (current_len < value_len) {
805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Finish this line -- write the current value.
806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      packet_size += AppendToBuffer(value_string + offset,
807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    current_len - offset,
808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    &buffer_write,
809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    &buffer_left);
810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      packet_size += AppendToBuffer("\n",
811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    strlen("\n"),
812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    &buffer_write,
813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    &buffer_left);
814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Advance to next value.
815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      offset = current_len + 1;
816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      current_len += 1 + strlen(value_string + offset);
817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Start another line -- add the header again.
818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      packet_size += AppendToBuffer(header_string,
819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    next->first.length(),
820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    &buffer_write,
821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    &buffer_left);
822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      packet_size += AppendToBuffer(": ",
823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    strlen(": "),
824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    &buffer_write,
825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    &buffer_left);
826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXPECT_EQ(value_len, current_len);
828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Copy the last (or only) value.
829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    packet_size += AppendToBuffer(value_string + offset,
830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  value_len - offset,
831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  &buffer_write,
832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  &buffer_left);
833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    packet_size += AppendToBuffer("\n",
834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  strlen("\n"),
835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  &buffer_write,
836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  &buffer_left);
837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return packet_size;
839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Create a MockWrite from the given SpdyFrame.
842c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMockWrite CreateMockWrite(const spdy::SpdyFrame& req) {
843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return MockWrite(
844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      true, req.data(), req.length() + spdy::SpdyFrame::size());
845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Create a MockWrite from the given SpdyFrame and sequence number.
848c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMockWrite CreateMockWrite(const spdy::SpdyFrame& req, int seq) {
8493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return CreateMockWrite(req, seq, true);
8503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
8513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
8523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Create a MockWrite from the given SpdyFrame and sequence number.
8533345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickMockWrite CreateMockWrite(const spdy::SpdyFrame& req, int seq, bool async) {
854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return MockWrite(
8553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      async, req.data(), req.length() + spdy::SpdyFrame::size(), seq);
856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Create a MockRead from the given SpdyFrame.
859c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMockRead CreateMockRead(const spdy::SpdyFrame& resp) {
860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return MockRead(
861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      true, resp.data(), resp.length() + spdy::SpdyFrame::size());
862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Create a MockRead from the given SpdyFrame and sequence number.
865c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMockRead CreateMockRead(const spdy::SpdyFrame& resp, int seq) {
8663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return CreateMockRead(resp, seq, true);
8673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
8683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
8693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Create a MockRead from the given SpdyFrame and sequence number.
8703345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickMockRead CreateMockRead(const spdy::SpdyFrame& resp, int seq, bool async) {
871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return MockRead(
8723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      async, resp.data(), resp.length() + spdy::SpdyFrame::size(), seq);
873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Combines the given SpdyFrames into the given char array and returns
876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the total length.
877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint CombineFrames(const spdy::SpdyFrame** frames, int num_frames,
878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  char* buff, int buff_len) {
879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int total_len = 0;
880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = 0; i < num_frames; ++i) {
881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    total_len += frames[i]->length() + spdy::SpdyFrame::size();
882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_LE(total_len, buff_len);
884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  char* ptr = buff;
885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = 0; i < num_frames; ++i) {
886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int len = frames[i]->length() + spdy::SpdyFrame::size();
887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    memcpy(ptr, frames[i]->data(), len);
888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ptr += len;
889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return total_len;
891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
89372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSpdySessionDependencies::SpdySessionDependencies()
894ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : host_resolver(new MockCachingHostResolver),
89572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      cert_verifier(new CertVerifier),
89672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      proxy_service(ProxyService::CreateDirect()),
89772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      ssl_config_service(new SSLConfigServiceDefaults),
89872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      socket_factory(new MockClientSocketFactory),
89972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      deterministic_socket_factory(new DeterministicMockClientSocketFactory),
90072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      http_auth_handler_factory(
90172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          HttpAuthHandlerFactory::CreateDefault(host_resolver.get())) {
90272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Note: The CancelledTransaction test does cleanup by running all
90372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // tasks in the message loop (RunAllPending).  Unfortunately, that
90472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // doesn't clean up tasks on the host resolver thread; and
90572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // TCPConnectJob is currently not cancellable.  Using synchronous
90672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // lookups allows the test to shutdown cleanly.  Until we have
90772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // cancellable TCPConnectJobs, use synchronous lookups.
90872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  host_resolver->set_synchronous_mode(true);
90972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
91072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
91172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSpdySessionDependencies::SpdySessionDependencies(ProxyService* proxy_service)
91272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    : host_resolver(new MockHostResolver),
91372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      cert_verifier(new CertVerifier),
91472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      proxy_service(proxy_service),
91572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      ssl_config_service(new SSLConfigServiceDefaults),
91672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      socket_factory(new MockClientSocketFactory),
91772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      deterministic_socket_factory(new DeterministicMockClientSocketFactory),
91872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      http_auth_handler_factory(
91972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          HttpAuthHandlerFactory::CreateDefault(host_resolver.get())) {}
92072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
92172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSpdySessionDependencies::~SpdySessionDependencies() {}
92272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
92372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static
92472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenHttpNetworkSession* SpdySessionDependencies::SpdyCreateSession(
92572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    SpdySessionDependencies* session_deps) {
92672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  net::HttpNetworkSession::Params params;
92772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  params.client_socket_factory = session_deps->socket_factory.get();
92872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  params.host_resolver = session_deps->host_resolver.get();
92972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  params.cert_verifier = session_deps->cert_verifier.get();
93072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  params.proxy_service = session_deps->proxy_service;
93172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  params.ssl_config_service = session_deps->ssl_config_service;
93272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  params.http_auth_handler_factory =
93372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      session_deps->http_auth_handler_factory.get();
93472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return new HttpNetworkSession(params);
93572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
93672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
93772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static
93872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenHttpNetworkSession* SpdySessionDependencies::SpdyCreateSessionDeterministic(
93972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    SpdySessionDependencies* session_deps) {
94072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  net::HttpNetworkSession::Params params;
94172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  params.client_socket_factory =
94272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      session_deps->deterministic_socket_factory.get();
94372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  params.host_resolver = session_deps->host_resolver.get();
94472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  params.cert_verifier = session_deps->cert_verifier.get();
94572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  params.proxy_service = session_deps->proxy_service;
94672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  params.ssl_config_service = session_deps->ssl_config_service;
94772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  params.http_auth_handler_factory =
94872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      session_deps->http_auth_handler_factory.get();
94972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return new HttpNetworkSession(params);
95072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
95172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
95272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSpdyURLRequestContext::SpdyURLRequestContext() {
953dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  set_host_resolver(new MockHostResolver());
954dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  set_cert_verifier(new CertVerifier);
955dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  set_proxy_service(ProxyService::CreateDirect());
956dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  set_ssl_config_service(new SSLConfigServiceDefaults);
957dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  set_http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault(
958dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      host_resolver()));
95972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  net::HttpNetworkSession::Params params;
96072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  params.client_socket_factory = &socket_factory_;
961dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  params.host_resolver = host_resolver();
962dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  params.cert_verifier = cert_verifier();
963dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  params.proxy_service = proxy_service();
964dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  params.ssl_config_service = ssl_config_service();
965dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  params.http_auth_handler_factory = http_auth_handler_factory();
966dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  params.network_delegate = network_delegate();
96772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  scoped_refptr<HttpNetworkSession> network_session(
96872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      new HttpNetworkSession(params));
969dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  set_http_transaction_factory(new HttpCache(
97072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      network_session,
971dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      HttpCache::DefaultBackend::InMemory(0)));
97272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
97372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
97472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSpdyURLRequestContext::~SpdyURLRequestContext() {
975dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delete http_transaction_factory();
976dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delete http_auth_handler_factory();
977dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delete cert_verifier();
978dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delete host_resolver();
97972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
98072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
9813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst SpdyHeaderInfo make_spdy_header(spdy::SpdyControlType type) {
9823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const SpdyHeaderInfo kHeader = {
9833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    type,                         // Kind = Syn
9843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    1,                            // Stream ID
9853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Associated stream ID
9863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    2,                            // Priority
9873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::CONTROL_FLAG_FIN,       // Control Flags
9883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    false,                        // Compressed
9893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::INVALID,                // Status
9903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NULL,                         // Data
9913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    0,                            // Length
9923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    spdy::DATA_FLAG_NONE          // Data Flags
9933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  };
9943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return kHeader;
9953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace net
997