mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-12-01 01:36:09 +03:00
150 lines
3.3 KiB
C++
150 lines
3.3 KiB
C++
|
// Copyright 2013 The Chromium Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
// found in the LICENSE file.
|
||
|
|
||
|
#include "net/websockets/websocket_extension_parser.h"
|
||
|
|
||
|
#include "base/logging.h"
|
||
|
#include "net/http/http_util.h"
|
||
|
|
||
|
namespace net {
|
||
|
|
||
|
WebSocketExtensionParser::WebSocketExtensionParser() = default;
|
||
|
|
||
|
WebSocketExtensionParser::~WebSocketExtensionParser() = default;
|
||
|
|
||
|
bool WebSocketExtensionParser::Parse(const char* data, size_t size) {
|
||
|
current_ = data;
|
||
|
end_ = data + size;
|
||
|
extensions_.clear();
|
||
|
|
||
|
bool failed = false;
|
||
|
|
||
|
do {
|
||
|
WebSocketExtension extension;
|
||
|
if (!ConsumeExtension(&extension)) {
|
||
|
failed = true;
|
||
|
break;
|
||
|
}
|
||
|
extensions_.push_back(extension);
|
||
|
|
||
|
ConsumeSpaces();
|
||
|
} while (ConsumeIfMatch(','));
|
||
|
|
||
|
if (!failed && current_ == end_)
|
||
|
return true;
|
||
|
|
||
|
extensions_.clear();
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool WebSocketExtensionParser::Consume(char c) {
|
||
|
ConsumeSpaces();
|
||
|
if (current_ == end_ || c != *current_)
|
||
|
return false;
|
||
|
++current_;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool WebSocketExtensionParser::ConsumeExtension(WebSocketExtension* extension) {
|
||
|
base::StringPiece name;
|
||
|
if (!ConsumeToken(&name))
|
||
|
return false;
|
||
|
*extension = WebSocketExtension(name.as_string());
|
||
|
|
||
|
while (ConsumeIfMatch(';')) {
|
||
|
WebSocketExtension::Parameter parameter((std::string()));
|
||
|
if (!ConsumeExtensionParameter(¶meter))
|
||
|
return false;
|
||
|
extension->Add(parameter);
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool WebSocketExtensionParser::ConsumeExtensionParameter(
|
||
|
WebSocketExtension::Parameter* parameter) {
|
||
|
base::StringPiece name, value;
|
||
|
std::string value_string;
|
||
|
|
||
|
if (!ConsumeToken(&name))
|
||
|
return false;
|
||
|
|
||
|
if (!ConsumeIfMatch('=')) {
|
||
|
*parameter = WebSocketExtension::Parameter(name.as_string());
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (Lookahead('\"')) {
|
||
|
if (!ConsumeQuotedToken(&value_string))
|
||
|
return false;
|
||
|
} else {
|
||
|
if (!ConsumeToken(&value))
|
||
|
return false;
|
||
|
value_string = value.as_string();
|
||
|
}
|
||
|
*parameter = WebSocketExtension::Parameter(name.as_string(), value_string);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool WebSocketExtensionParser::ConsumeToken(base::StringPiece* token) {
|
||
|
ConsumeSpaces();
|
||
|
const char* head = current_;
|
||
|
while (current_ < end_ && HttpUtil::IsTokenChar(*current_))
|
||
|
++current_;
|
||
|
if (current_ == head)
|
||
|
return false;
|
||
|
*token = base::StringPiece(head, current_ - head);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool WebSocketExtensionParser::ConsumeQuotedToken(std::string* token) {
|
||
|
if (!Consume('"'))
|
||
|
return false;
|
||
|
|
||
|
*token = "";
|
||
|
while (current_ < end_ && *current_ != '"') {
|
||
|
if (*current_ == '\\') {
|
||
|
++current_;
|
||
|
if (current_ == end_)
|
||
|
return false;
|
||
|
}
|
||
|
if (!HttpUtil::IsTokenChar(*current_))
|
||
|
return false;
|
||
|
*token += *current_;
|
||
|
++current_;
|
||
|
}
|
||
|
if (current_ == end_)
|
||
|
return false;
|
||
|
DCHECK_EQ(*current_, '"');
|
||
|
|
||
|
++current_;
|
||
|
|
||
|
return !token->empty();
|
||
|
}
|
||
|
|
||
|
void WebSocketExtensionParser::ConsumeSpaces() {
|
||
|
while (current_ < end_ && (*current_ == ' ' || *current_ == '\t'))
|
||
|
++current_;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
bool WebSocketExtensionParser::Lookahead(char c) {
|
||
|
const char* head = current_;
|
||
|
bool result = Consume(c);
|
||
|
current_ = head;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
bool WebSocketExtensionParser::ConsumeIfMatch(char c) {
|
||
|
const char* head = current_;
|
||
|
if (!Consume(c)) {
|
||
|
current_ = head;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
} // namespace net
|