Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(919)

Side by Side Diff: net/websockets/websocket_extension_parser.cc

Issue 23872029: Implement WebSocketExtensionParser (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/websockets/websocket_extension_parser.h"
6
7 #include "base/strings/string_util.h"
8
9 namespace net {
10
11 namespace {
12
13 const char kHeaderFieldName[] = "Sec-WebSocket-Extensions";
Adam Rice 2013/09/17 04:30:32 Please use the declaration in websocket_handshake_
yhirano 2013/09/17 06:03:31 Sorry, I don't need it anymore. I deleted it.
14
15 } // namespace
16
17 // Backup the head pointer if the parser has error.
18 class WebSocketExtensionParser::CurrentPointerBackup {
19 public:
20 explicit CurrentPointerBackup(WebSocketExtensionParser* parser);
21 ~CurrentPointerBackup();
22
23 private:
24 WebSocketExtensionParser* parser_;
25 const char* original_head_;
26 };
27
28 WebSocketExtensionParser::CurrentPointerBackup::CurrentPointerBackup(
29 WebSocketExtensionParser* parser)
30 : parser_(parser), original_head_(parser->current_) {}
31
32 WebSocketExtensionParser::CurrentPointerBackup::~CurrentPointerBackup() {
33 if (parser_->has_error_)
34 parser_->current_ = original_head_;
35 }
36
37 WebSocketExtensionParser::WebSocketExtensionParser() {}
38
39 WebSocketExtensionParser::~WebSocketExtensionParser() {}
40
41 void WebSocketExtensionParser::Parse(const char* data, size_t size) {
42 current_ = data;
43 end_ = &data[size];
44 extensions_.clear();
45 has_error_ = false;
46 CurrentPointerBackup backup(this);
47
48 ConsumeExtensionList();
49 has_error_ = has_error_ || (current_ != end_);
50 if (has_error_)
51 extensions_.clear();
52 }
53
54
55 void WebSocketExtensionParser::Clear() {
56 current_ = NULL;
57 end_ = NULL;
58 has_error_ = false;
59 extensions_.clear();
60 }
61
62 void WebSocketExtensionParser::Consume(const char* data,
63 size_t size,
64 bool with_lws) {
65 DCHECK(!has_error_);
66 CurrentPointerBackup backup(this);
67 if (with_lws) {
68 ConsumeLWS();
69 if (has_error_)
70 return;
71 }
72 if (UnconsumedBytes() < size) {
73 has_error_ = true;
74 return;
75 }
76 if (memcmp(data, current_, size)) {
77 has_error_ = true;
78 return;
79 }
80 current_ += size;
81 }
82
83 void WebSocketExtensionParser::ConsumeExtensionList() {
84 DCHECK(!has_error_);
85 WebSocketExtension extension("");
86 ConsumeExtension(&extension);
87 if (has_error_) return;
88 do {
89 extensions_.push_back(extension);
90 ConsumeExtension(&extension);
91 } while (!has_error_);
92 has_error_ = false;
93 }
94
95 void WebSocketExtensionParser::ConsumeExtension(WebSocketExtension* extension) {
96 DCHECK(!has_error_);
97 CurrentPointerBackup backup(this);
98 base::StringPiece name;
99 ConsumeToken(&name);
100 if (has_error_) return;
101 *extension = WebSocketExtension(name.as_string());
102
103
104 while (true) {
105 Consume(";", 1);
106 if (has_error_) {
107 has_error_ = false;
108 return;
109 }
110 WebSocketExtension::Parameter parameter("");
111 ConsumeExtensionParameter(&parameter);
112 if (has_error_) return;
113 extension->Add(parameter);
114 }
115 }
116
117 void WebSocketExtensionParser::ConsumeExtensionParameter(
118 WebSocketExtension::Parameter* parameter) {
119 DCHECK(!has_error_);
120 CurrentPointerBackup backup(this);
121 base::StringPiece name, value;
122 std::string value_string;
123
124 ConsumeToken(&name);
125 if (has_error_) return;
126 Consume("=", 1);
127 if (has_error_) {
128 has_error_ = false;
129 *parameter = WebSocketExtension::Parameter(name.as_string());
130 return;
131 }
132
133 ConsumeToken(&value);
134 if (has_error_) {
135 has_error_ = false;
136 ConsumeQuotedToken(&value_string);
137 if (has_error_) return;
138 } else {
139 value_string = value.as_string();
140 }
141 *parameter = WebSocketExtension::Parameter(name.as_string(), value_string);
142 }
143
144 void WebSocketExtensionParser::ConsumeToken(base::StringPiece* token) {
145 DCHECK(!has_error_);
146 CurrentPointerBackup backup(this);
147 ConsumeLWS();
148 DCHECK(!has_error_);
149 const char* head = current_;
150 while (current_ < end_ &&
151 !IsControl(current_[0]) && !IsSeparator(current_[0]))
152 ++current_;
153 if (current_ == head) {
154 has_error_ = true;
155 return;
156 }
157 *token = base::StringPiece(head, current_ - head);
158 }
159
160 void WebSocketExtensionParser::ConsumeQuotedToken(std::string* token) {
161 DCHECK(!has_error_);
162 CurrentPointerBackup backup(this);
163 Consume("\"", 1);
164 if (has_error_) return;
165 *token = "";
166 while (current_ < end_ && !IsControl(current_[0])) {
167 if (UnconsumedBytes() >= 2 && current_[0] == '\\') {
168 char next = current_[1];
169 if (IsControl(next) || IsSeparator(next)) break;
170 *token += next;
171 current_ += 2;
172 } else if (IsSeparator(current_[0])) {
173 break;
174 } else {
175 *token += current_[0];
176 ++current_;
177 }
178 }
179 Consume("\"", 1);
180 if (has_error_) return;
181 has_error_ = token->empty();
182 }
183
184 // Unlike the "implied *LWS" specification in RFC2616, this parser
185 // consumes *LWS, because there are no adjacent tokens in WebSocket
186 // extension grammer.
187 void WebSocketExtensionParser::ConsumeLWS() {
188 DCHECK(!has_error_);
189 size_t counter = 0;
190 while (current_ < end_) {
191 if (current_[0] == ' ' || current_[0] == '\t') {
192 while (current_ < end_ && (current_[0] == ' ' || current_[0] == '\t'))
193 ++current_;
194 } else if (UnconsumedBytes() >= 3 &&
195 current_[0] == '\r' && current_[1] == '\n' &&
196 (current_[2] == ' ' || current_[2] == '\t')) {
197 current_ += 2;
198 while (current_ < end_ && (current_[0] == ' ' || current_[0] == '\t'))
199 ++current_;
200 break;
201 } else {
202 break;
203 }
204 ++counter;
205 }
206 return;
207 }
208
209 // static
210 bool WebSocketExtensionParser::IsControl(char c) {
211 return (0 <= c && c <= 31) || c == 127;
212 }
213
214 // static
215 bool WebSocketExtensionParser::IsSeparator(char c) {
216 const char separators[] = "()<>@,;:\\\"/[]?={} \t";
217 return strchr(separators, c);
218 }
219
220 } // namespace net
OLDNEW
« no previous file with comments | « net/websockets/websocket_extension_parser.h ('k') | net/websockets/websocket_extension_parser_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698