made http_parser not use exceptions
This commit is contained in:
parent
599ed646f0
commit
6c42830f97
|
@ -86,7 +86,8 @@ namespace libtorrent
|
|||
buffer::const_interval get_body() const;
|
||||
bool header_finished() const { return m_state == read_body; }
|
||||
bool finished() const { return m_finished; }
|
||||
boost::tuple<int, int> incoming(buffer::const_interval recv_buffer);
|
||||
boost::tuple<int, int> incoming(buffer::const_interval recv_buffer
|
||||
, bool& error);
|
||||
int body_start() const { return m_body_start_pos; }
|
||||
int content_length() const { return m_content_length; }
|
||||
|
||||
|
@ -104,7 +105,7 @@ namespace libtorrent
|
|||
|
||||
int m_content_length;
|
||||
|
||||
enum { read_status, read_header, read_body } m_state;
|
||||
enum { read_status, read_header, read_body, error_state } m_state;
|
||||
|
||||
std::map<std::string, std::string> m_header;
|
||||
buffer::const_interval m_recv_buffer;
|
||||
|
|
|
@ -285,15 +285,13 @@ void http_connection::on_read(asio::error_code const& e
|
|||
{
|
||||
libtorrent::buffer::const_interval rcv_buf(&m_recvbuffer[0]
|
||||
, &m_recvbuffer[0] + m_read_pos);
|
||||
try
|
||||
bool error = false;
|
||||
m_parser.incoming(rcv_buf, error);
|
||||
if (error)
|
||||
{
|
||||
m_parser.incoming(rcv_buf);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
m_timer.cancel();
|
||||
m_handler(asio::error::fault, m_parser, 0, 0);
|
||||
m_handler.clear();
|
||||
// HTTP parse error
|
||||
asio::error_code ec = asio::error::fault;
|
||||
callback(ec, 0, 0);
|
||||
return;
|
||||
}
|
||||
if (!m_bottled && m_parser.header_finished())
|
||||
|
|
|
@ -104,7 +104,8 @@ namespace libtorrent
|
|||
, m_finished(false)
|
||||
{}
|
||||
|
||||
boost::tuple<int, int> http_parser::incoming(buffer::const_interval recv_buffer)
|
||||
boost::tuple<int, int> http_parser::incoming(
|
||||
buffer::const_interval recv_buffer, bool& error)
|
||||
{
|
||||
TORRENT_ASSERT(recv_buffer.left() >= m_recv_buffer.left());
|
||||
boost::tuple<int, int> ret(0, 0);
|
||||
|
@ -113,6 +114,12 @@ namespace libtorrent
|
|||
if (recv_buffer.left() == m_recv_buffer.left()) return ret;
|
||||
m_recv_buffer = recv_buffer;
|
||||
|
||||
if (m_state == error_state)
|
||||
{
|
||||
error = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
char const* pos = recv_buffer.begin + m_recv_pos;
|
||||
if (m_state == read_status)
|
||||
{
|
||||
|
@ -122,7 +129,11 @@ namespace libtorrent
|
|||
if (newline == recv_buffer.end) return ret;
|
||||
|
||||
if (newline == pos)
|
||||
throw std::runtime_error("unexpected newline in HTTP response");
|
||||
{
|
||||
m_state = error_state;
|
||||
error = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
char const* line_end = newline;
|
||||
if (pos != line_end && *(line_end - 1) == '\r') --line_end;
|
||||
|
@ -211,7 +222,9 @@ namespace libtorrent
|
|||
range_str >> range_start >> dummy >> range_end;
|
||||
if (!range_str || range_end < range_start)
|
||||
{
|
||||
throw std::runtime_error("invalid content-range in HTTP response: " + range_str.str());
|
||||
m_state = error_state;
|
||||
error = true;
|
||||
return ret;
|
||||
}
|
||||
// the http range is inclusive
|
||||
m_content_length = range_end - range_start + 1;
|
||||
|
@ -316,8 +329,11 @@ namespace libtorrent
|
|||
|
||||
std::size_t pos = request.find("announce");
|
||||
if (pos == std::string::npos)
|
||||
throw std::runtime_error("scrape is not available on url: '"
|
||||
+ tracker_req().url +"'");
|
||||
{
|
||||
fail(-1, ("scrape is not available on url: '"
|
||||
+ tracker_req().url +"'").c_str());
|
||||
return;
|
||||
}
|
||||
request.replace(pos, 8, "scrape");
|
||||
}
|
||||
|
||||
|
@ -670,8 +686,13 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
m_recv_pos += bytes_transferred;
|
||||
bool e = false;
|
||||
m_parser.incoming(buffer::const_interval(&m_buffer[0]
|
||||
, &m_buffer[0] + m_recv_pos));
|
||||
, &m_buffer[0] + m_recv_pos), e);
|
||||
if (e)
|
||||
{
|
||||
fail(-1, "incorrect http response");
|
||||
}
|
||||
|
||||
// if the receive buffer is full, expand it with http_buffer_size
|
||||
if ((int)m_buffer.size() == m_recv_pos)
|
||||
|
|
|
@ -123,9 +123,11 @@ void lsd::on_announce(udp::endpoint const& from, char* buffer
|
|||
|
||||
http_parser p;
|
||||
|
||||
p.incoming(buffer::const_interval(buffer, buffer + bytes_transferred));
|
||||
bool error = false;
|
||||
p.incoming(buffer::const_interval(buffer, buffer + bytes_transferred)
|
||||
, error);
|
||||
|
||||
if (!p.header_finished())
|
||||
if (!p.header_finished() || error)
|
||||
{
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
m_log << time_now_string()
|
||||
|
|
14
src/upnp.cpp
14
src/upnp.cpp
|
@ -266,16 +266,14 @@ try
|
|||
|
||||
*/
|
||||
http_parser p;
|
||||
try
|
||||
{
|
||||
p.incoming(buffer::const_interval(buffer
|
||||
, buffer + bytes_transferred));
|
||||
}
|
||||
catch (std::exception& e)
|
||||
bool error = false;
|
||||
p.incoming(buffer::const_interval(buffer
|
||||
, buffer + bytes_transferred), error);
|
||||
if (error)
|
||||
{
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
m_log << time_now_string()
|
||||
<< " <== (" << from << ") Rootdevice responded with incorrect HTTP packet. Ignoring device (" << e.what() << ")" << std::endl;
|
||||
m_log << time_now_string() << " <== (" << from << ") Rootdevice "
|
||||
"responded with incorrect HTTP packet. Ignoring device" << std::endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -315,7 +315,6 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
// throws exception when the client should be disconnected
|
||||
void web_peer_connection::on_receive(asio::error_code const& error
|
||||
, std::size_t bytes_transferred)
|
||||
{
|
||||
|
@ -344,9 +343,13 @@ namespace libtorrent
|
|||
bool header_finished = m_parser.header_finished();
|
||||
if (!header_finished)
|
||||
{
|
||||
boost::tie(payload, protocol) = m_parser.incoming(recv_buffer);
|
||||
bool error = false;
|
||||
boost::tie(payload, protocol) = m_parser.incoming(recv_buffer, error);
|
||||
m_statistics.received_bytes(payload, protocol);
|
||||
|
||||
if (error)
|
||||
throw std::runtime_error("failed to parse HTTP response");
|
||||
|
||||
TORRENT_ASSERT(recv_buffer.left() == 0 || *recv_buffer.begin == 'H');
|
||||
|
||||
TORRENT_ASSERT(recv_buffer.left() <= packet_size());
|
||||
|
|
|
@ -18,17 +18,19 @@ using namespace libtorrent;
|
|||
using namespace boost::tuples;
|
||||
using boost::bind;
|
||||
|
||||
tuple<int, int> feed_bytes(http_parser& parser, char const* str)
|
||||
tuple<int, int, bool> feed_bytes(http_parser& parser, char const* str)
|
||||
{
|
||||
tuple<int, int> ret(0, 0);
|
||||
tuple<int, int, bool> ret(0, 0, false);
|
||||
buffer::const_interval recv_buf(str, str + 1);
|
||||
for (; *str; ++str)
|
||||
{
|
||||
recv_buf.end = str + 1;
|
||||
int payload, protocol;
|
||||
tie(payload, protocol) = parser.incoming(recv_buf);
|
||||
bool error = false;
|
||||
tie(payload, protocol) = parser.incoming(recv_buf, error);
|
||||
ret.get<0>() += payload;
|
||||
ret.get<1>() += protocol;
|
||||
ret.get<2>() += error;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -135,14 +137,14 @@ int test_main()
|
|||
// HTTP request parser
|
||||
|
||||
http_parser parser;
|
||||
boost::tuple<int, int> received = feed_bytes(parser
|
||||
boost::tuple<int, int, bool> received = feed_bytes(parser
|
||||
, "HTTP/1.1 200 OK\r\n"
|
||||
"Content-Length: 4\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"\r\n"
|
||||
"test");
|
||||
|
||||
TEST_CHECK(received == make_tuple(4, 64));
|
||||
TEST_CHECK(received == make_tuple(4, 64, false));
|
||||
TEST_CHECK(parser.finished());
|
||||
TEST_CHECK(std::equal(parser.get_body().begin, parser.get_body().end, "test"));
|
||||
TEST_CHECK(parser.header("content-type") == "text/plain");
|
||||
|
@ -164,7 +166,7 @@ int test_main()
|
|||
|
||||
received = feed_bytes(parser, upnp_response);
|
||||
|
||||
TEST_CHECK(received == make_tuple(0, int(strlen(upnp_response))));
|
||||
TEST_CHECK(received == make_tuple(0, int(strlen(upnp_response)), false));
|
||||
TEST_CHECK(parser.get_body().left() == 0);
|
||||
TEST_CHECK(parser.header("st") == "upnp:rootdevice");
|
||||
TEST_CHECK(parser.header("location")
|
||||
|
@ -187,7 +189,7 @@ int test_main()
|
|||
|
||||
received = feed_bytes(parser, upnp_notify);
|
||||
|
||||
TEST_CHECK(received == make_tuple(0, int(strlen(upnp_notify))));
|
||||
TEST_CHECK(received == make_tuple(0, int(strlen(upnp_notify)), false));
|
||||
TEST_CHECK(parser.method() == "notify");
|
||||
TEST_CHECK(parser.path() == "*");
|
||||
|
||||
|
@ -202,7 +204,7 @@ int test_main()
|
|||
|
||||
received = feed_bytes(parser, bt_lsd);
|
||||
|
||||
TEST_CHECK(received == make_tuple(2, int(strlen(bt_lsd) - 2)));
|
||||
TEST_CHECK(received == make_tuple(2, int(strlen(bt_lsd) - 2), false));
|
||||
TEST_CHECK(parser.method() == "bt-search");
|
||||
TEST_CHECK(parser.path() == "*");
|
||||
TEST_CHECK(atoi(parser.header("port").c_str()) == 6881);
|
||||
|
@ -223,7 +225,7 @@ int test_main()
|
|||
|
||||
received = feed_bytes(parser, tracker_response);
|
||||
|
||||
TEST_CHECK(received == make_tuple(5, int(strlen(tracker_response) - 5)));
|
||||
TEST_CHECK(received == make_tuple(5, int(strlen(tracker_response) - 5), false));
|
||||
TEST_CHECK(parser.get_body().left() == 5);
|
||||
|
||||
// test xml parser
|
||||
|
|
Loading…
Reference in New Issue