1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/spdy/spdy_websocket_test_util.h"
6
7#include "net/spdy/buffered_spdy_framer.h"
8#include "net/spdy/spdy_http_utils.h"
9
10namespace net {
11
12static const int kDefaultAssociatedStreamId = 0;
13static const bool kDefaultCompressed = false;
14static const char* const kDefaultDataPointer = NULL;
15static const uint32 kDefaultDataLength = 0;
16static const char** const kDefaultExtraHeaders = NULL;
17static const int kDefaultExtraHeaderCount = 0;
18
19SpdyWebSocketTestUtil::SpdyWebSocketTestUtil(
20    NextProto protocol) : spdy_util_(protocol) {}
21
22std::string SpdyWebSocketTestUtil::GetHeader(const SpdyHeaderBlock& headers,
23                                             const std::string& key) const {
24  SpdyHeaderBlock::const_iterator it = headers.find(GetHeaderKey(key));
25  return (it == headers.end()) ? "" : it->second;
26}
27
28void SpdyWebSocketTestUtil::SetHeader(
29    const std::string& key,
30    const std::string& value,
31    SpdyHeaderBlock* headers) const {
32  (*headers)[GetHeaderKey(key)] = value;
33}
34
35SpdyFrame* SpdyWebSocketTestUtil::ConstructSpdyWebSocketSynStream(
36    int stream_id,
37    const char* path,
38    const char* host,
39    const char* origin) {
40  scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock());
41  SetHeader("path", path, headers.get());
42  SetHeader("host", host, headers.get());
43  SetHeader("version", "WebSocket/13", headers.get());
44  SetHeader("scheme", "ws", headers.get());
45  SetHeader("origin", origin, headers.get());
46  return spdy_util_.ConstructSpdyControlFrame(headers.Pass(),
47                                              /*compressed*/ false,
48                                              stream_id,
49                                              HIGHEST,
50                                              SYN_STREAM,
51                                              CONTROL_FLAG_NONE,
52                                              0);
53}
54
55SpdyFrame* SpdyWebSocketTestUtil::ConstructSpdyWebSocketSynReply(
56    int stream_id) {
57  scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock());
58  SetHeader("status", "101", headers.get());
59  return spdy_util_.ConstructSpdyControlFrame(headers.Pass(),
60                                              false,
61                                              stream_id,
62                                              LOWEST,
63                                              SYN_REPLY,
64                                              CONTROL_FLAG_NONE,
65                                              0);
66}
67
68SpdyFrame* SpdyWebSocketTestUtil::ConstructSpdyWebSocketHandshakeRequestFrame(
69    scoped_ptr<SpdyHeaderBlock> headers,
70    SpdyStreamId stream_id,
71    RequestPriority request_priority) {
72  // SPDY SYN_STREAM control frame header.
73  const SpdyHeaderInfo kSynStreamHeader = {
74    SYN_STREAM,
75    stream_id,
76    kDefaultAssociatedStreamId,
77    ConvertRequestPriorityToSpdyPriority(request_priority, 2),
78    kSpdyCredentialSlotUnused,
79    CONTROL_FLAG_NONE,
80    kDefaultCompressed,
81    RST_STREAM_INVALID,
82    kDefaultDataPointer,
83    kDefaultDataLength,
84    DATA_FLAG_NONE
85  };
86
87  // Construct SPDY SYN_STREAM control frame.
88  return spdy_util_.ConstructSpdyFrame(
89      kSynStreamHeader,
90      headers.Pass());
91}
92
93SpdyFrame* SpdyWebSocketTestUtil::ConstructSpdyWebSocketHandshakeResponseFrame(
94    scoped_ptr<SpdyHeaderBlock> headers,
95    SpdyStreamId stream_id,
96    RequestPriority request_priority) {
97  // SPDY SYN_REPLY control frame header.
98  const SpdyHeaderInfo kSynReplyHeader = {
99    SYN_REPLY,
100    stream_id,
101    kDefaultAssociatedStreamId,
102    ConvertRequestPriorityToSpdyPriority(request_priority, 2),
103    kSpdyCredentialSlotUnused,
104    CONTROL_FLAG_NONE,
105    kDefaultCompressed,
106    RST_STREAM_INVALID,
107    kDefaultDataPointer,
108    kDefaultDataLength,
109    DATA_FLAG_NONE
110  };
111
112  // Construct SPDY SYN_REPLY control frame.
113  return spdy_util_.ConstructSpdyFrame(
114      kSynReplyHeader,
115      headers.Pass());
116}
117
118SpdyFrame* SpdyWebSocketTestUtil::ConstructSpdyWebSocketHeadersFrame(
119    int stream_id,
120    const char* length,
121    bool fin) {
122  scoped_ptr<SpdyHeaderBlock> headers(new SpdyHeaderBlock());
123  SetHeader("opcode", "1", headers.get());  // text frame
124  SetHeader("length", length, headers.get());
125  SetHeader("fin", fin ? "1" : "0", headers.get());
126  return spdy_util_.ConstructSpdyControlFrame(headers.Pass(),
127                                              /*compression*/ false,
128                                              stream_id,
129                                              LOWEST,
130                                              HEADERS,
131                                              CONTROL_FLAG_NONE,
132                                              0);
133}
134
135SpdyFrame* SpdyWebSocketTestUtil::ConstructSpdyWebSocketDataFrame(
136    const char* data,
137    int len,
138    SpdyStreamId stream_id,
139    bool fin) {
140
141  // Construct SPDY data frame.
142  BufferedSpdyFramer framer(spdy_util_.spdy_version(), false);
143  return framer.CreateDataFrame(
144      stream_id,
145      data,
146      len,
147      fin ? DATA_FLAG_FIN : DATA_FLAG_NONE);
148}
149
150SpdyFrame* SpdyWebSocketTestUtil::ConstructSpdySettings(
151    const SettingsMap& settings) const {
152  return spdy_util_.ConstructSpdySettings(settings);
153}
154
155SpdyMajorVersion SpdyWebSocketTestUtil::spdy_version() const {
156  return spdy_util_.spdy_version();
157}
158
159std::string SpdyWebSocketTestUtil::GetHeaderKey(
160    const std::string& key) const {
161  return (spdy_util_.is_spdy2() ? "" : ":") + key;
162}
163
164}  // namespace net
165