mirror of
https://github.com/boostorg/asio.git
synced 2026-01-28 06:42:08 +00:00
Fix compile error in regex overload of async_read_until.hpp. Fixes #5688 Explicitly specify the signal() function from the global namespace. Fixes #5722 Don't read the clock unless the heap is non-empty. Change the SSL buffers sizes so that they're large enough to hold a complete TLS record. Fixes #5854 Make sure the synchronous null_buffers operations obey the user's non_blocking setting. Fixes #5756 Set size of select fd_set at runtime when using Windows. Disable warning due to const qualifier being applied to function type. Fix crash due to gcc_x86_fenced_block that shows up when using the Intel C++ compiler. Fixes #5763 Specialise operations for buffer sequences that are arrays of exactly two buffers. Initialise all OpenSSL algorithms. Fix error mapping when session is gracefully shut down. Various performance improvements: * Split the task_io_service's run and poll code. * Use thread-local operation queues in single-threaded use cases (i.e. concurrency_hint is 1) to eliminate a lock/unlock pair. * Only fence block exit when a handler is being run directly out of the io_service. * Prefer x86 mfence-based fenced block when available. * Use a plain ol' long for the atomic_count when all thread support is disabled. * Allow some epoll_reactor speculative operations to be performed without holding the lock. * Improve locality of reference by performing an epoll_reactor's I/O operation immediately before the corresponding handler is called. This also improves scalability across CPUs when multiple threads are running the io_service. * Pass same error_code variable through to each operation's complete() function. * Optimise creation of and access to the io_service implementation. Remove unused state in HTTP server examples. Add latency test programs. [SVN r74863]
316 lines
6.1 KiB
C++
316 lines
6.1 KiB
C++
//
|
|
// request_parser.cpp
|
|
// ~~~~~~~~~~~~~~~~~~
|
|
//
|
|
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
//
|
|
|
|
#include "request_parser.hpp"
|
|
#include "request.hpp"
|
|
|
|
namespace http {
|
|
namespace server3 {
|
|
|
|
request_parser::request_parser()
|
|
: state_(method_start)
|
|
{
|
|
}
|
|
|
|
void request_parser::reset()
|
|
{
|
|
state_ = method_start;
|
|
}
|
|
|
|
boost::tribool request_parser::consume(request& req, char input)
|
|
{
|
|
switch (state_)
|
|
{
|
|
case method_start:
|
|
if (!is_char(input) || is_ctl(input) || is_tspecial(input))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
state_ = method;
|
|
req.method.push_back(input);
|
|
return boost::indeterminate;
|
|
}
|
|
case method:
|
|
if (input == ' ')
|
|
{
|
|
state_ = uri;
|
|
return boost::indeterminate;
|
|
}
|
|
else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
req.method.push_back(input);
|
|
return boost::indeterminate;
|
|
}
|
|
case uri:
|
|
if (input == ' ')
|
|
{
|
|
state_ = http_version_h;
|
|
return boost::indeterminate;
|
|
}
|
|
else if (is_ctl(input))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
req.uri.push_back(input);
|
|
return boost::indeterminate;
|
|
}
|
|
case http_version_h:
|
|
if (input == 'H')
|
|
{
|
|
state_ = http_version_t_1;
|
|
return boost::indeterminate;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
case http_version_t_1:
|
|
if (input == 'T')
|
|
{
|
|
state_ = http_version_t_2;
|
|
return boost::indeterminate;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
case http_version_t_2:
|
|
if (input == 'T')
|
|
{
|
|
state_ = http_version_p;
|
|
return boost::indeterminate;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
case http_version_p:
|
|
if (input == 'P')
|
|
{
|
|
state_ = http_version_slash;
|
|
return boost::indeterminate;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
case http_version_slash:
|
|
if (input == '/')
|
|
{
|
|
req.http_version_major = 0;
|
|
req.http_version_minor = 0;
|
|
state_ = http_version_major_start;
|
|
return boost::indeterminate;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
case http_version_major_start:
|
|
if (is_digit(input))
|
|
{
|
|
req.http_version_major = req.http_version_major * 10 + input - '0';
|
|
state_ = http_version_major;
|
|
return boost::indeterminate;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
case http_version_major:
|
|
if (input == '.')
|
|
{
|
|
state_ = http_version_minor_start;
|
|
return boost::indeterminate;
|
|
}
|
|
else if (is_digit(input))
|
|
{
|
|
req.http_version_major = req.http_version_major * 10 + input - '0';
|
|
return boost::indeterminate;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
case http_version_minor_start:
|
|
if (is_digit(input))
|
|
{
|
|
req.http_version_minor = req.http_version_minor * 10 + input - '0';
|
|
state_ = http_version_minor;
|
|
return boost::indeterminate;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
case http_version_minor:
|
|
if (input == '\r')
|
|
{
|
|
state_ = expecting_newline_1;
|
|
return boost::indeterminate;
|
|
}
|
|
else if (is_digit(input))
|
|
{
|
|
req.http_version_minor = req.http_version_minor * 10 + input - '0';
|
|
return boost::indeterminate;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
case expecting_newline_1:
|
|
if (input == '\n')
|
|
{
|
|
state_ = header_line_start;
|
|
return boost::indeterminate;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
case header_line_start:
|
|
if (input == '\r')
|
|
{
|
|
state_ = expecting_newline_3;
|
|
return boost::indeterminate;
|
|
}
|
|
else if (!req.headers.empty() && (input == ' ' || input == '\t'))
|
|
{
|
|
state_ = header_lws;
|
|
return boost::indeterminate;
|
|
}
|
|
else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
req.headers.push_back(header());
|
|
req.headers.back().name.push_back(input);
|
|
state_ = header_name;
|
|
return boost::indeterminate;
|
|
}
|
|
case header_lws:
|
|
if (input == '\r')
|
|
{
|
|
state_ = expecting_newline_2;
|
|
return boost::indeterminate;
|
|
}
|
|
else if (input == ' ' || input == '\t')
|
|
{
|
|
return boost::indeterminate;
|
|
}
|
|
else if (is_ctl(input))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
state_ = header_value;
|
|
req.headers.back().value.push_back(input);
|
|
return boost::indeterminate;
|
|
}
|
|
case header_name:
|
|
if (input == ':')
|
|
{
|
|
state_ = space_before_header_value;
|
|
return boost::indeterminate;
|
|
}
|
|
else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
req.headers.back().name.push_back(input);
|
|
return boost::indeterminate;
|
|
}
|
|
case space_before_header_value:
|
|
if (input == ' ')
|
|
{
|
|
state_ = header_value;
|
|
return boost::indeterminate;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
case header_value:
|
|
if (input == '\r')
|
|
{
|
|
state_ = expecting_newline_2;
|
|
return boost::indeterminate;
|
|
}
|
|
else if (is_ctl(input))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
req.headers.back().value.push_back(input);
|
|
return boost::indeterminate;
|
|
}
|
|
case expecting_newline_2:
|
|
if (input == '\n')
|
|
{
|
|
state_ = header_line_start;
|
|
return boost::indeterminate;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
case expecting_newline_3:
|
|
return (input == '\n');
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool request_parser::is_char(int c)
|
|
{
|
|
return c >= 0 && c <= 127;
|
|
}
|
|
|
|
bool request_parser::is_ctl(int c)
|
|
{
|
|
return (c >= 0 && c <= 31) || (c == 127);
|
|
}
|
|
|
|
bool request_parser::is_tspecial(int c)
|
|
{
|
|
switch (c)
|
|
{
|
|
case '(': case ')': case '<': case '>': case '@':
|
|
case ',': case ';': case ':': case '\\': case '"':
|
|
case '/': case '[': case ']': case '?': case '=':
|
|
case '{': case '}': case ' ': case '\t':
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool request_parser::is_digit(int c)
|
|
{
|
|
return c >= '0' && c <= '9';
|
|
}
|
|
|
|
} // namespace server3
|
|
} // namespace http
|