|
|
@ -24,12 +24,15 @@ namespace dap {
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ContentReader
|
|
|
|
// ContentReader
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
ContentReader::ContentReader(const std::shared_ptr<Reader>& reader)
|
|
|
|
ContentReader::ContentReader(
|
|
|
|
: reader(reader) {}
|
|
|
|
const std::shared_ptr<Reader>& reader,
|
|
|
|
|
|
|
|
OnInvalidData on_invalid_data /* = OnInvalidData::kIgnore */)
|
|
|
|
|
|
|
|
: reader(reader), on_invalid_data(on_invalid_data) {}
|
|
|
|
|
|
|
|
|
|
|
|
ContentReader& ContentReader::operator=(ContentReader&& rhs) noexcept {
|
|
|
|
ContentReader& ContentReader::operator=(ContentReader&& rhs) noexcept {
|
|
|
|
buf = std::move(rhs.buf);
|
|
|
|
buf = std::move(rhs.buf);
|
|
|
|
reader = std::move(rhs.reader);
|
|
|
|
reader = std::move(rhs.reader);
|
|
|
|
|
|
|
|
on_invalid_data = std::move(rhs.on_invalid_data);
|
|
|
|
return *this;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -44,17 +47,19 @@ void ContentReader::close() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string ContentReader::read() {
|
|
|
|
std::string ContentReader::read() {
|
|
|
|
matched_idx = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Find Content-Length header prefix
|
|
|
|
// Find Content-Length header prefix
|
|
|
|
if (!scan("Content-Length:")) {
|
|
|
|
if (on_invalid_data == kClose) {
|
|
|
|
return "";
|
|
|
|
if (!match("Content-Length:")) {
|
|
|
|
|
|
|
|
return badHeader();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (!scan("Content-Length:")) {
|
|
|
|
|
|
|
|
return "";
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Skip whitespace and tabs
|
|
|
|
// Skip whitespace and tabs
|
|
|
|
while (matchAny(" \t")) {
|
|
|
|
while (matchAny(" \t")) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Parse length
|
|
|
|
// Parse length
|
|
|
|
size_t len = 0;
|
|
|
|
size_t len = 0;
|
|
|
|
while (true) {
|
|
|
|
while (true) {
|
|
|
@ -68,20 +73,16 @@ std::string ContentReader::read() {
|
|
|
|
if (len == 0) {
|
|
|
|
if (len == 0) {
|
|
|
|
return "";
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Expect \r\n\r\n
|
|
|
|
// Expect \r\n\r\n
|
|
|
|
if (!match("\r\n\r\n")) {
|
|
|
|
if (!match("\r\n\r\n")) {
|
|
|
|
return "";
|
|
|
|
return badHeader();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Read message
|
|
|
|
// Read message
|
|
|
|
if (!buffer(len + matched_idx)) {
|
|
|
|
if (!buffer(len)) {
|
|
|
|
return "";
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < matched_idx; i++) {
|
|
|
|
|
|
|
|
buf.pop_front();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string out;
|
|
|
|
std::string out;
|
|
|
|
out.reserve(len);
|
|
|
|
out.reserve(len);
|
|
|
|
for (size_t i = 0; i < len; i++) {
|
|
|
|
for (size_t i = 0; i < len; i++) {
|
|
|
@ -107,17 +108,18 @@ bool ContentReader::scan(const char* str) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool ContentReader::match(const uint8_t* seq, size_t len) {
|
|
|
|
bool ContentReader::match(const uint8_t* seq, size_t len) {
|
|
|
|
if (!buffer(len + matched_idx)) {
|
|
|
|
if (!buffer(len)) {
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
auto it = matched_idx;
|
|
|
|
auto it = buf.begin();
|
|
|
|
for (size_t i = 0; i < len; i++, it++) {
|
|
|
|
for (size_t i = 0; i < len; i++, it++) {
|
|
|
|
if (buf[it] != seq[i]) {
|
|
|
|
if (*it != seq[i]) {
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < len; i++) {
|
|
|
|
matched_idx += len;
|
|
|
|
buf.pop_front();
|
|
|
|
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -127,12 +129,12 @@ bool ContentReader::match(const char* str) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char ContentReader::matchAny(const char* chars) {
|
|
|
|
char ContentReader::matchAny(const char* chars) {
|
|
|
|
if (!buffer(1 + matched_idx)) {
|
|
|
|
if (!buffer(1)) {
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int c = buf[matched_idx];
|
|
|
|
int c = buf.front();
|
|
|
|
if (auto p = strchr(chars, c)) {
|
|
|
|
if (auto p = strchr(chars, c)) {
|
|
|
|
matched_idx++;
|
|
|
|
buf.pop_front();
|
|
|
|
return *p;
|
|
|
|
return *p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
@ -158,6 +160,13 @@ bool ContentReader::buffer(size_t bytes) {
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string ContentReader::badHeader() {
|
|
|
|
|
|
|
|
if (on_invalid_data == kClose) {
|
|
|
|
|
|
|
|
close();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return "";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ContentWriter
|
|
|
|
// ContentWriter
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|