forked from premiere/premiere-libtorrent
handle errors in peer_connection
This commit is contained in:
parent
56ca5fa63c
commit
347555ea8f
|
@ -214,6 +214,7 @@ nobase_include_HEADERS = \
|
|||
aux_/array.hpp \
|
||||
aux_/ip_notifier.hpp \
|
||||
aux_/noexcept_movable.hpp \
|
||||
aux_/torrent_impl.hpp \
|
||||
\
|
||||
extensions/smart_ban.hpp \
|
||||
extensions/ut_metadata.hpp \
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2003-2017, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TORRENT_TORRENT_IMPL_HPP_INCLUDED
|
||||
#define TORRENT_TORRENT_IMPL_HPP_INCLUDED
|
||||
|
||||
// this is not a normal header, it's just this template, to be able to call this
|
||||
// function from more than one translation unit. But it's still internal
|
||||
|
||||
namespace libtorrent {
|
||||
|
||||
template <typename Fun, typename... Args>
|
||||
void torrent::wrap(Fun f, Args&&... a)
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try
|
||||
#endif
|
||||
{
|
||||
(this->*f)(std::forward<Args>(a)...);
|
||||
}
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
catch (system_error const& e) {
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
debug_log("EXCEPTION: (%d %s) %s"
|
||||
, e.code().value()
|
||||
, e.code().message().c_str()
|
||||
, e.what());
|
||||
#endif
|
||||
alerts().emplace_alert<torrent_error_alert>(get_handle()
|
||||
, e.code(), e.what());
|
||||
pause();
|
||||
} catch (std::exception const& e) {
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
debug_log("EXCEPTION: %s", e.what());
|
||||
#endif
|
||||
alerts().emplace_alert<torrent_error_alert>(get_handle()
|
||||
, error_code(), e.what());
|
||||
pause();
|
||||
} catch (...) {
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
debug_log("EXCEPTION: unknown");
|
||||
#endif
|
||||
alerts().emplace_alert<torrent_error_alert>(get_handle()
|
||||
, error_code(), "unknown error");
|
||||
pause();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -505,7 +505,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
constexpr std::size_t TORRENT_READ_HANDLER_MAX_SIZE = 400;
|
||||
# else
|
||||
// if this is not divisible by 8, we're wasting space
|
||||
constexpr std::size_t TORRENT_READ_HANDLER_MAX_SIZE = 336;
|
||||
constexpr std::size_t TORRENT_READ_HANDLER_MAX_SIZE = 342;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
@ -514,7 +514,7 @@ constexpr std::size_t TORRENT_READ_HANDLER_MAX_SIZE = 336;
|
|||
constexpr std::size_t TORRENT_WRITE_HANDLER_MAX_SIZE = 400;
|
||||
# else
|
||||
// if this is not divisible by 8, we're wasting space
|
||||
constexpr std::size_t TORRENT_WRITE_HANDLER_MAX_SIZE = 336;
|
||||
constexpr std::size_t TORRENT_WRITE_HANDLER_MAX_SIZE = 342;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
|
|
@ -989,6 +989,10 @@ namespace aux {
|
|||
bandwidth_channel m_bandwidth_channel[num_channels];
|
||||
|
||||
protected:
|
||||
|
||||
template <typename Fun, typename... Args>
|
||||
void wrap(Fun f, Args&&... a);
|
||||
|
||||
// statistics about upload and download speeds
|
||||
// and total amount of uploads and downloads for
|
||||
// this peer
|
||||
|
|
|
@ -301,13 +301,13 @@ struct TORRENT_EXTRA_EXPORT utp_stream
|
|||
{
|
||||
if (!endpoint.address().is_v4())
|
||||
{
|
||||
m_io_service.post(std::bind<void>(handler, boost::asio::error::operation_not_supported, 0));
|
||||
m_io_service.post(std::bind<void>(handler, boost::asio::error::operation_not_supported));
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_impl == nullptr)
|
||||
{
|
||||
m_io_service.post(std::bind<void>(handler, boost::asio::error::not_connected, 0));
|
||||
m_io_service.post(std::bind<void>(handler, boost::asio::error::not_connected));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -320,14 +320,14 @@ struct TORRENT_EXTRA_EXPORT utp_stream
|
|||
{
|
||||
if (m_impl == nullptr)
|
||||
{
|
||||
m_io_service.post(std::bind<void>(handler, boost::asio::error::not_connected, 0));
|
||||
m_io_service.post(std::bind<void>(handler, boost::asio::error::not_connected, std::size_t(0)));
|
||||
return;
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(!m_read_handler);
|
||||
if (m_read_handler)
|
||||
{
|
||||
m_io_service.post(std::bind<void>(handler, boost::asio::error::operation_not_supported, 0));
|
||||
m_io_service.post(std::bind<void>(handler, boost::asio::error::operation_not_supported, std::size_t(0)));
|
||||
return;
|
||||
}
|
||||
std::size_t bytes_added = 0;
|
||||
|
@ -349,7 +349,7 @@ struct TORRENT_EXTRA_EXPORT utp_stream
|
|||
{
|
||||
// if we're reading 0 bytes, post handler immediately
|
||||
// asio's SSL layer depends on this behavior
|
||||
m_io_service.post(std::bind<void>(handler, error_code(), 0));
|
||||
m_io_service.post(std::bind<void>(handler, error_code(), std::size_t(0)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -362,7 +362,7 @@ struct TORRENT_EXTRA_EXPORT utp_stream
|
|||
{
|
||||
if (m_impl == nullptr)
|
||||
{
|
||||
m_io_service.post(std::bind<void>(handler, boost::asio::error::not_connected, 0));
|
||||
m_io_service.post(std::bind<void>(handler, boost::asio::error::not_connected, std::size_t(0)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -370,7 +370,7 @@ struct TORRENT_EXTRA_EXPORT utp_stream
|
|||
if (m_read_handler)
|
||||
{
|
||||
TORRENT_ASSERT_FAIL(); // we should never do this!
|
||||
m_io_service.post(std::bind<void>(handler, boost::asio::error::operation_not_supported, 0));
|
||||
m_io_service.post(std::bind<void>(handler, boost::asio::error::operation_not_supported, std::size_t(0)));
|
||||
return;
|
||||
}
|
||||
m_read_handler = handler;
|
||||
|
@ -464,7 +464,7 @@ struct TORRENT_EXTRA_EXPORT utp_stream
|
|||
if (m_impl == nullptr)
|
||||
{
|
||||
m_io_service.post(std::bind<void>(handler
|
||||
, boost::asio::error::not_connected, 0));
|
||||
, boost::asio::error::not_connected, std::size_t(0)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -472,7 +472,7 @@ struct TORRENT_EXTRA_EXPORT utp_stream
|
|||
if (m_write_handler)
|
||||
{
|
||||
m_io_service.post(std::bind<void>(handler
|
||||
, boost::asio::error::operation_not_supported, 0));
|
||||
, boost::asio::error::operation_not_supported, std::size_t(0)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -495,7 +495,7 @@ struct TORRENT_EXTRA_EXPORT utp_stream
|
|||
{
|
||||
// if we're writing 0 bytes, post handler immediately
|
||||
// asio's SSL layer depends on this behavior
|
||||
m_io_service.post(std::bind<void>(handler, error_code(), 0));
|
||||
m_io_service.post(std::bind<void>(handler, error_code(), std::size_t(0)));
|
||||
return;
|
||||
}
|
||||
m_write_handler = handler;
|
||||
|
|
|
@ -80,6 +80,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/hex.hpp" // to_hex
|
||||
#endif
|
||||
|
||||
#include "libtorrent/aux_/torrent_impl.hpp"
|
||||
|
||||
//#define TORRENT_CORRUPT_DATA
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
@ -144,13 +146,13 @@ namespace libtorrent {
|
|||
, m_slow_start(true)
|
||||
{
|
||||
m_counters.inc_stats_counter(counters::num_tcp_peers + m_socket->type() - 1);
|
||||
std::shared_ptr<torrent> t = m_torrent.lock();
|
||||
|
||||
if (m_connected)
|
||||
m_counters.inc_stats_counter(counters::num_peers_connected);
|
||||
else if (m_connecting)
|
||||
m_counters.inc_stats_counter(counters::num_peers_half_open);
|
||||
|
||||
std::shared_ptr<torrent> t = m_torrent.lock();
|
||||
// if t is nullptr, we better not be connecting, since
|
||||
// we can't decrement the connecting counter
|
||||
TORRENT_ASSERT(t || !m_connecting);
|
||||
|
@ -185,6 +187,41 @@ namespace libtorrent {
|
|||
#endif
|
||||
}
|
||||
|
||||
template <typename Fun, typename... Args>
|
||||
void peer_connection::wrap(Fun f, Args&&... a)
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try
|
||||
#endif
|
||||
{
|
||||
(this->*f)(std::forward<Args>(a)...);
|
||||
}
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
catch (std::bad_alloc const&) {
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
peer_log(peer_log_alert::info, "EXCEPTION", "bad_alloc");
|
||||
#endif
|
||||
disconnect(make_error_code(boost::system::errc::not_enough_memory)
|
||||
, operation_t::unknown);
|
||||
}
|
||||
catch (system_error const& e) {
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
peer_log(peer_log_alert::info, "EXCEPTION", "(%d %s) %s"
|
||||
, e.code().value()
|
||||
, e.code().message().c_str()
|
||||
, e.what());
|
||||
#endif
|
||||
disconnect(e.code(), operation_t::unknown);
|
||||
}
|
||||
catch (std::exception const& e) {
|
||||
TORRENT_UNUSED(e);
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
peer_log(peer_log_alert::info, "EXCEPTION", "%s", e.what());
|
||||
#endif
|
||||
disconnect(make_error_code(boost::system::errc::not_enough_memory)
|
||||
, operation_t::sock_write);
|
||||
}
|
||||
#endif // BOOST_NO_EXCEPTIONS
|
||||
|
||||
int peer_connection::timeout() const
|
||||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
|
@ -384,8 +421,9 @@ namespace libtorrent {
|
|||
, t->num_peers());
|
||||
#endif
|
||||
|
||||
auto conn = self();
|
||||
m_socket->async_connect(m_remote
|
||||
, std::bind(&peer_connection::on_connection_complete, self(), _1));
|
||||
, [conn](error_code const& e) { conn->wrap(&peer_connection::on_connection_complete, e); });
|
||||
m_connect = aux::time_now();
|
||||
|
||||
sent_syn(m_remote.address().is_v6());
|
||||
|
@ -415,7 +453,8 @@ namespace libtorrent {
|
|||
// to not trigger another one. This effectively defer
|
||||
// the update until the current message queue is
|
||||
// flushed
|
||||
m_ios.post(std::bind(&peer_connection::do_update_interest, self()));
|
||||
auto conn = self();
|
||||
m_ios.post([conn] { conn->wrap(&peer_connection::do_update_interest); });
|
||||
}
|
||||
m_need_interest_update = true;
|
||||
}
|
||||
|
@ -2812,9 +2851,10 @@ namespace libtorrent {
|
|||
|
||||
if (t->is_deleted()) return;
|
||||
|
||||
auto conn = self();
|
||||
bool const exceeded = m_disk_thread.async_write(t->storage(), p, data, self()
|
||||
, std::bind(&peer_connection::on_disk_write_complete
|
||||
, self(), _1, p, t));
|
||||
, [conn, p, t] (storage_error const& e)
|
||||
{ conn->wrap(&peer_connection::on_disk_write_complete, e, p, t); });
|
||||
|
||||
// every peer is entitled to have two disk blocks allocated at any given
|
||||
// time, regardless of whether the cache size is exceeded or not. If this
|
||||
|
@ -3026,7 +3066,8 @@ namespace libtorrent {
|
|||
// piece are done, and we can restore it, allowing
|
||||
// new requests to it
|
||||
m_disk_thread.async_clear_piece(t->storage(), p.piece
|
||||
, std::bind(&torrent::on_piece_fail_sync, t, _1, block_finished));
|
||||
, [t, block_finished] (piece_index_t pi)
|
||||
{ t->wrap(&torrent::on_piece_fail_sync, pi, block_finished); });
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -5141,9 +5182,10 @@ namespace libtorrent {
|
|||
#endif
|
||||
// this means we're in seed mode and we haven't yet
|
||||
// verified this piece (r.piece)
|
||||
auto conn = self();
|
||||
m_disk_thread.async_hash(t->storage(), r.piece, {}
|
||||
, std::bind(&peer_connection::on_seed_mode_hashed, self()
|
||||
, _1, _2, _3));
|
||||
, [conn](piece_index_t p, sha1_hash const& ph, storage_error const& e) {
|
||||
conn->wrap(&peer_connection::on_seed_mode_hashed, p, ph, e); });
|
||||
t->verifying(r.piece);
|
||||
continue;
|
||||
}
|
||||
|
@ -5177,9 +5219,10 @@ namespace libtorrent {
|
|||
TORRENT_ASSERT(r.piece >= piece_index_t(0));
|
||||
TORRENT_ASSERT(r.piece < t->torrent_file().end_piece());
|
||||
|
||||
auto conn = self();
|
||||
m_disk_thread.async_read(t->storage(), r
|
||||
, std::bind(&peer_connection::on_disk_read_complete
|
||||
, self(), _1, _2, _3, r, clock_type::now()));
|
||||
, [conn, r](disk_buffer_holder buf, disk_job_flags_t f, storage_error const& ec)
|
||||
{ conn->wrap(&peer_connection::on_disk_read_complete, std::move(buf), f, ec, r, clock_type::now()); });
|
||||
}
|
||||
m_last_sent_payload = clock_type::now();
|
||||
m_requests.erase(m_requests.begin() + i);
|
||||
|
@ -5606,8 +5649,10 @@ namespace libtorrent {
|
|||
m_socket_is_writing = true;
|
||||
#endif
|
||||
|
||||
m_socket->async_write_some(vec, make_handler(std::bind(
|
||||
&peer_connection::on_send_data, self(), _1, _2)
|
||||
auto conn = self();
|
||||
m_socket->async_write_some(vec, make_handler(
|
||||
[conn](error_code const& ec, std::size_t bt)
|
||||
{ conn->wrap(&peer_connection::on_send_data, ec, bt); }
|
||||
, m_write_handler_storage, *this));
|
||||
|
||||
m_channel_state[upload_channel] |= peer_info::bw_network;
|
||||
|
@ -5691,9 +5736,11 @@ namespace libtorrent {
|
|||
|
||||
// utp sockets aren't thread safe...
|
||||
ADD_OUTSTANDING_ASYNC("peer_connection::on_receive_data");
|
||||
auto conn = self();
|
||||
m_socket->async_read_some(
|
||||
boost::asio::mutable_buffers_1(vec.data(), vec.size()), make_handler(
|
||||
std::bind(&peer_connection::on_receive_data, self(), _1, _2)
|
||||
[conn](error_code const& ec, std::size_t bt)
|
||||
{ conn->wrap(&peer_connection::on_receive_data, ec, bt); }
|
||||
, m_read_handler_storage, *this));
|
||||
}
|
||||
|
||||
|
|
|
@ -103,6 +103,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/aux_/session_impl.hpp" // for tracker_logger
|
||||
#endif
|
||||
|
||||
#include "libtorrent/aux_/torrent_impl.hpp"
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
namespace libtorrent {
|
||||
|
@ -4550,42 +4552,6 @@ namespace libtorrent {
|
|||
return detail::read_uint32(ptr);
|
||||
}
|
||||
|
||||
template <typename Fun, typename... Args>
|
||||
void torrent::wrap(Fun f, Args&&... a)
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
try
|
||||
#endif
|
||||
{
|
||||
(this->*f)(std::forward<Args>(a)...);
|
||||
}
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
catch (system_error const& e) {
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
debug_log("EXCEPTION: (%d %s) %s"
|
||||
, e.code().value()
|
||||
, e.code().message().c_str()
|
||||
, e.what());
|
||||
#endif
|
||||
alerts().emplace_alert<torrent_error_alert>(get_handle()
|
||||
, e.code(), e.what());
|
||||
pause();
|
||||
} catch (std::exception const& e) {
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
debug_log("EXCEPTION: %s", e.what());
|
||||
#endif
|
||||
alerts().emplace_alert<torrent_error_alert>(get_handle()
|
||||
, error_code(), e.what());
|
||||
pause();
|
||||
} catch (...) {
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
debug_log("EXCEPTION: unknown");
|
||||
#endif
|
||||
alerts().emplace_alert<torrent_error_alert>(get_handle()
|
||||
, error_code(), "unknown error");
|
||||
pause();
|
||||
}
|
||||
#endif
|
||||
|
||||
void torrent::cancel_non_critical()
|
||||
{
|
||||
std::set<piece_index_t> time_critical;
|
||||
|
|
Loading…
Reference in New Issue