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

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 // Backup the head pointer if the parser has error.
Adam Rice 2013/09/17 04:30:33 I think this grammar can be parsed with single-cha
yhirano 2013/09/17 06:03:31 I deleted some |has_error_ = false| statements. Th
12 class WebSocketExtensionParser::CurrentPointerBackup {
13 public:
14 explicit CurrentPointerBackup(WebSocketExtensionParser* parser);
15 ~CurrentPointerBackup();
16
17 private:
18 WebSocketExtensionParser* parser_;
19 const char* original_head_;
20 };
21
22 WebSocketExtensionParser::CurrentPointerBackup::CurrentPointerBackup(
23 WebSocketExtensionParser* parser)
24 : parser_(parser), original_head_(parser->current_) {}
25
26 WebSocketExtensionParser::CurrentPointerBackup::~CurrentPointerBackup() {
27 if (parser_->has_error_)
28 parser_->current_ = original_head_;
29 }
30
31 WebSocketExtensionParser::WebSocketExtensionParser() {}
32
33 WebSocketExtensionParser::~WebSocketExtensionParser() {}
34
35 void WebSocketExtensionParser::Parse(const char* data, size_t size) {
36 current_ = data;
37 end_ = &data[size];
38 extensions_.clear();
39 has_error_ = false;
40 CurrentPointerBackup backup(this);
41
42 ConsumeExtensionList();
43 has_error_ = has_error_ || (current_ != end_);
44 if (has_error_)
45 extensions_.clear();
46 }
47
48 void WebSocketExtensionParser::Consume(const char* data, size_t size) {
49 DCHECK(!has_error_);
50 CurrentPointerBackup backup(this);
51 ConsumeLWS();
52 DCHECK(!has_error_);
53 if (UnconsumedBytes() < size) {
54 has_error_ = true;
55 return;
56 }
57 if (memcmp(data, current_, size)) {
58 has_error_ = true;
59 return;
60 }
61 current_ += size;
62 }
63
64 void WebSocketExtensionParser::ConsumeExtensionList() {
65 DCHECK(!has_error_);
66 WebSocketExtension extension("");
67 ConsumeExtension(&extension);
68 if (has_error_) return;
69 do {
70 extensions_.push_back(extension);
71 ConsumeExtension(&extension);
72 } while (!has_error_);
73 has_error_ = false;
74 }
75
76 void WebSocketExtensionParser::ConsumeExtension(WebSocketExtension* extension) {
77 DCHECK(!has_error_);
78 CurrentPointerBackup backup(this);
79 base::StringPiece name;
80 ConsumeToken(&name);
81 if (has_error_) return;
82 *extension = WebSocketExtension(name.as_string());
83
84
85 while (true) {
86 Consume(";", 1);
87 if (has_error_) {
88 has_error_ = false;
89 return;
90 }
91 WebSocketExtension::Parameter parameter("");
92 ConsumeExtensionParameter(&parameter);
93 if (has_error_) return;
94 extension->Add(parameter);
95 }
96 }
97
98 void WebSocketExtensionParser::ConsumeExtensionParameter(
99 WebSocketExtension::Parameter* parameter) {
100 DCHECK(!has_error_);
101 CurrentPointerBackup backup(this);
102 base::StringPiece name, value;
103 std::string value_string;
104
105 ConsumeToken(&name);
106 if (has_error_) return;
107 Consume("=", 1);
108 if (has_error_) {
109 has_error_ = false;
110 *parameter = WebSocketExtension::Parameter(name.as_string());
111 return;
112 }
113
114 ConsumeToken(&value);
115 if (has_error_) {
116 has_error_ = false;
117 ConsumeQuotedToken(&value_string);
118 if (has_error_) return;
119 } else {
120 value_string = value.as_string();
121 }
122 *parameter = WebSocketExtension::Parameter(name.as_string(), value_string);
123 }
124
125 void WebSocketExtensionParser::ConsumeToken(base::StringPiece* token) {
126 DCHECK(!has_error_);
127 CurrentPointerBackup backup(this);
128 ConsumeLWS();
129 DCHECK(!has_error_);
130 const char* head = current_;
131 while (current_ < end_ &&
132 !IsControl(current_[0]) && !IsSeparator(current_[0]))
133 ++current_;
134 if (current_ == head) {
135 has_error_ = true;
136 return;
137 }
138 *token = base::StringPiece(head, current_ - head);
139 }
140
141 void WebSocketExtensionParser::ConsumeQuotedToken(std::string* token) {
142 DCHECK(!has_error_);
143 CurrentPointerBackup backup(this);
144 Consume("\"", 1);
145 if (has_error_) return;
146 *token = "";
147 while (current_ < end_ && !IsControl(current_[0])) {
148 if (UnconsumedBytes() >= 2 && current_[0] == '\\') {
149 char next = current_[1];
150 if (IsControl(next) || IsSeparator(next)) break;
151 *token += next;
152 current_ += 2;
153 } else if (IsSeparator(current_[0])) {
154 break;
155 } else {
156 *token += current_[0];
157 ++current_;
158 }
159 }
160 Consume("\"", 1);
161 has_error_ = has_error_ || token->empty();
162 }
163
164 // Unlike the "implied *LWS" specification in RFC2616, this parser
165 // consumes *LWS, because there are no adjacent tokens in WebSocket
166 // extension grammer.
167 void WebSocketExtensionParser::ConsumeLWS() {
168 DCHECK(!has_error_);
169 size_t counter = 0;
170 while (current_ < end_) {
171 if (current_[0] == ' ' || current_[0] == '\t') {
172 while (current_ < end_ && (current_[0] == ' ' || current_[0] == '\t'))
173 ++current_;
174 } else if (UnconsumedBytes() >= 3 &&
175 current_[0] == '\r' && current_[1] == '\n' &&
176 (current_[2] == ' ' || current_[2] == '\t')) {
177 current_ += 2;
178 while (current_ < end_ && (current_[0] == ' ' || current_[0] == '\t'))
179 ++current_;
180 break;
181 } else {
182 break;
183 }
184 ++counter;
185 }
186 return;
187 }
188
189 // static
190 bool WebSocketExtensionParser::IsControl(char c) {
191 return (0 <= c && c <= 31) || c == 127;
192 }
193
194 // static
195 bool WebSocketExtensionParser::IsSeparator(char c) {
196 const char separators[] = "()<>@,;:\\\"/[]?={} \t";
197 return strchr(separators, c);
198 }
199
200 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698