forked from premiere/premiere-libtorrent
fixed a serious bug where corrupt messages could be sent out.
This commit is contained in:
parent
d1c33c0d2b
commit
18cb6736ea
|
@ -147,17 +147,15 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
template<class InIt>
|
||||
std::string read_string(InIt& in, InIt end, int len)
|
||||
void read_string(InIt& in, InIt end, int len, std::string& str)
|
||||
{
|
||||
assert(len >= 0);
|
||||
std::string ret;
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
if (in == end) throw invalid_encoding();
|
||||
ret += *in;
|
||||
str += *in;
|
||||
++in;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class OutIt>
|
||||
|
@ -265,7 +263,7 @@ namespace libtorrent
|
|||
++in; // ':'
|
||||
int len = std::atoi(len_s.c_str());
|
||||
ret = entry(entry::string_t);
|
||||
ret.string() = read_string(in, end, len);
|
||||
read_string(in, end, len, ret.string());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -313,7 +313,8 @@ namespace libtorrent
|
|||
int send_buffer_size() const
|
||||
{
|
||||
return (int)m_send_buffer[0].size()
|
||||
+ (int)m_send_buffer[1].size();
|
||||
+ (int)m_send_buffer[1].size()
|
||||
- m_write_pos;
|
||||
}
|
||||
|
||||
buffer::const_interval receive_buffer() const
|
||||
|
@ -384,11 +385,17 @@ namespace libtorrent
|
|||
// waiting for a async_write operation on one
|
||||
// buffer, the other is used to write data to
|
||||
// be queued up.
|
||||
buffer m_send_buffer[2];
|
||||
std::vector<char> m_send_buffer[2];
|
||||
// buffer m_send_buffer[2];
|
||||
// the current send buffer is the one to write to.
|
||||
// (m_current_send_buffer + 1) % 2 is the
|
||||
// buffer we're currently waiting for.
|
||||
int m_current_send_buffer;
|
||||
|
||||
// if the sending buffer doesn't finish in one send
|
||||
// operation, this is the position within that buffer
|
||||
// wher the next operation should continue
|
||||
int m_write_pos;
|
||||
|
||||
// timeouts
|
||||
boost::posix_time::ptime m_last_receive;
|
||||
|
|
|
@ -60,8 +60,6 @@ namespace libtorrent
|
|||
{
|
||||
assert(given <= max);
|
||||
assert(given >= min);
|
||||
// TODO: TEMP!
|
||||
// assert(given >= used);
|
||||
return given - used;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace libtorrent
|
|||
: piece_timeout(120)
|
||||
, request_queue_time(3.f)
|
||||
, sequenced_download_threshold(7)
|
||||
, max_allowed_request_queue(200)
|
||||
{}
|
||||
|
||||
// the number of seconds from a request is sent until
|
||||
|
@ -62,6 +63,14 @@ namespace libtorrent
|
|||
// for example, if the threshold is 7, all pieces which 7
|
||||
// or more peers have, will be downloaded in index order.
|
||||
int sequenced_download_threshold;
|
||||
|
||||
// the number of outstanding block requests a peer is
|
||||
// allowed to queue up in the client. If a peer sends
|
||||
// more requests than this (before the first one has
|
||||
// been sent) the last request will be dropped.
|
||||
// the higher this is, the faster upload speeds the
|
||||
// client can get to a single peer.
|
||||
int max_allowed_request_queue;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -64,10 +64,10 @@ namespace libtorrent
|
|||
, m_mean_download_payload_rate(0)
|
||||
, m_mean_upload_payload_rate(0)
|
||||
{
|
||||
std::fill(m_download_rate_history, m_download_rate_history+history, 0);
|
||||
std::fill(m_upload_rate_history, m_upload_rate_history+history, 0);
|
||||
std::fill(m_download_payload_rate_history, m_download_payload_rate_history+history, 0);
|
||||
std::fill(m_upload_payload_rate_history, m_upload_payload_rate_history+history, 0);
|
||||
std::fill(m_download_rate_history, m_download_rate_history+history, 0.f);
|
||||
std::fill(m_upload_rate_history, m_upload_rate_history+history, 0.f);
|
||||
std::fill(m_download_payload_rate_history, m_download_payload_rate_history+history, 0.f);
|
||||
std::fill(m_upload_payload_rate_history, m_upload_payload_rate_history+history, 0.f);
|
||||
}
|
||||
|
||||
void operator+=(const stat& s)
|
||||
|
|
|
@ -622,7 +622,7 @@ namespace libtorrent
|
|||
|
||||
int extended_id = detail::read_uint8(recv_buffer.begin);
|
||||
|
||||
if (extended_id >= 0 && extended_id < num_supported_extensions
|
||||
if (extended_id > 0 && extended_id < num_supported_extensions
|
||||
&& !m_ses.m_extension_enabled[extended_id])
|
||||
throw protocol_error("'extended' message using disabled extension");
|
||||
|
||||
|
@ -1188,6 +1188,8 @@ namespace libtorrent
|
|||
|
||||
void bt_peer_connection::write_piece(peer_request const& r)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
const int packet_size = 4 + 5 + 4 + r.length;
|
||||
|
||||
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
||||
|
@ -1425,7 +1427,9 @@ namespace libtorrent
|
|||
if (packet_size > 1024*1024 || packet_size < 0)
|
||||
{
|
||||
// packet too large
|
||||
throw std::runtime_error("packet > 1 MB");
|
||||
throw std::runtime_error("packet > 1 MB ("
|
||||
+ boost::lexical_cast<std::string>(
|
||||
(unsigned int)packet_size) + " bytes)");
|
||||
}
|
||||
|
||||
if (packet_size == 0)
|
||||
|
@ -1530,6 +1534,15 @@ namespace libtorrent
|
|||
{
|
||||
if (!m_in_constructor)
|
||||
peer_connection::check_invariant();
|
||||
|
||||
if (!m_payloads.empty())
|
||||
{
|
||||
for (std::deque<range>::const_iterator i = m_payloads.begin();
|
||||
i != m_payloads.end() - 1; ++i)
|
||||
{
|
||||
assert(i->start + i->length <= (i+1)->start);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -87,6 +87,7 @@ namespace libtorrent
|
|||
, m_packet_size(0)
|
||||
, m_recv_pos(0)
|
||||
, m_current_send_buffer(0)
|
||||
, m_write_pos(0)
|
||||
, m_last_receive(second_clock::universal_time())
|
||||
, m_last_sent(second_clock::universal_time())
|
||||
, m_socket(s)
|
||||
|
@ -176,6 +177,7 @@ namespace libtorrent
|
|||
, m_packet_size(0)
|
||||
, m_recv_pos(0)
|
||||
, m_current_send_buffer(0)
|
||||
, m_write_pos(0)
|
||||
, m_last_receive(second_clock::universal_time())
|
||||
, m_last_sent(second_clock::universal_time())
|
||||
, m_socket(s)
|
||||
|
@ -790,7 +792,7 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
if (m_requests.size() > 100)
|
||||
if (m_requests.size() > m_ses.m_settings.max_allowed_request_queue)
|
||||
{
|
||||
// don't allow clients to abuse our
|
||||
// memory consumption.
|
||||
|
@ -1604,19 +1606,26 @@ namespace libtorrent
|
|||
|
||||
assert(!m_writing);
|
||||
|
||||
int sending_buffer = (m_current_send_buffer + 1) & 1;
|
||||
if (m_send_buffer[sending_buffer].empty())
|
||||
{
|
||||
// thise means we have to swap buffer, because there's no
|
||||
// previous buffer we're still waiting for.
|
||||
std::swap(m_current_send_buffer, sending_buffer);
|
||||
m_write_pos = 0;
|
||||
}
|
||||
|
||||
// send the actual buffer
|
||||
if (!m_send_buffer[m_current_send_buffer].empty())
|
||||
if (!m_send_buffer[sending_buffer].empty())
|
||||
{
|
||||
int amount_to_send
|
||||
= std::min(m_ul_bandwidth_quota.left()
|
||||
, (int)m_send_buffer[m_current_send_buffer].size());
|
||||
, (int)m_send_buffer[sending_buffer].size() - m_write_pos);
|
||||
|
||||
assert(amount_to_send > 0);
|
||||
|
||||
/*
|
||||
buffer::interval_type send_buffer
|
||||
= m_send_buffer[m_current_send_buffer].data();
|
||||
// swap the send buffer for the double buffered effect
|
||||
m_current_send_buffer = (m_current_send_buffer + 1) & 1;
|
||||
= m_send_buffer[sending_buffer].data();
|
||||
|
||||
// we have data that's scheduled for sending
|
||||
int to_send = std::min(int(send_buffer.first.end - send_buffer.first.begin)
|
||||
|
@ -1634,6 +1643,15 @@ namespace libtorrent
|
|||
assert(m_ul_bandwidth_quota.left() >= int(buffer_size(bufs[0]) + buffer_size(bufs[1])));
|
||||
m_socket->async_write_some(bufs, bind(&peer_connection::on_send_data
|
||||
, self(), _1, _2));
|
||||
*/
|
||||
|
||||
assert(m_write_pos < (int)m_send_buffer[sending_buffer].size());
|
||||
m_socket->async_write_some(asio::buffer(
|
||||
&m_send_buffer[sending_buffer][m_write_pos], amount_to_send)
|
||||
, bind(&peer_connection::on_send_data, self(), _1, _2));
|
||||
|
||||
// --------------
|
||||
|
||||
m_writing = true;
|
||||
m_last_write_size = amount_to_send;
|
||||
m_ul_bandwidth_quota.used += m_last_write_size;
|
||||
|
@ -1678,7 +1696,8 @@ namespace libtorrent
|
|||
|
||||
void peer_connection::send_buffer(char const* begin, char const* end)
|
||||
{
|
||||
m_send_buffer[m_current_send_buffer].insert(begin, end);
|
||||
m_send_buffer[m_current_send_buffer].insert(
|
||||
m_send_buffer[m_current_send_buffer].end(), begin, end);
|
||||
setup_send();
|
||||
}
|
||||
|
||||
|
@ -1686,7 +1705,11 @@ namespace libtorrent
|
|||
// return value is destructed
|
||||
buffer::interval peer_connection::allocate_send_buffer(int size)
|
||||
{
|
||||
return m_send_buffer[m_current_send_buffer].allocate(size);
|
||||
m_send_buffer[m_current_send_buffer].resize(m_send_buffer[m_current_send_buffer].size() + size);
|
||||
buffer::interval ret(&m_send_buffer[m_current_send_buffer][m_send_buffer[m_current_send_buffer].size() - size]
|
||||
, &m_send_buffer[m_current_send_buffer][0] + m_send_buffer[m_current_send_buffer].size());
|
||||
return ret;
|
||||
// return m_send_buffer[m_current_send_buffer].allocate(size);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
|
@ -1715,6 +1738,7 @@ namespace libtorrent
|
|||
|
||||
assert(m_reading);
|
||||
assert(m_last_read_size > 0);
|
||||
assert(m_last_read_size >= bytes_transferred);
|
||||
m_reading = false;
|
||||
// correct the dl quota usage, if not all of the buffer was actually read
|
||||
m_dl_bandwidth_quota.used -= m_last_read_size - bytes_transferred;
|
||||
|
@ -1828,7 +1852,6 @@ namespace libtorrent
|
|||
(*m_ses.m_logger) << "CONNECTION FAILED: " << m_remote.address().to_string() << "\n";
|
||||
#endif
|
||||
m_ses.connection_failed(m_socket, m_remote, e.what());
|
||||
// disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1873,27 +1896,28 @@ namespace libtorrent
|
|||
// correct the ul quota usage, if not all of the buffer was sent
|
||||
m_ul_bandwidth_quota.used -= m_last_write_size - bytes_transferred;
|
||||
m_last_write_size = 0;
|
||||
m_write_pos += bytes_transferred;
|
||||
|
||||
if (error)
|
||||
throw std::runtime_error(error.what());
|
||||
if (m_disconnecting) return;
|
||||
|
||||
assert(!m_connecting);
|
||||
// assert(bytes_transferred > 0);
|
||||
assert(bytes_transferred > 0);
|
||||
|
||||
int sending_buffer = (m_current_send_buffer + 1) & 1;
|
||||
m_send_buffer[sending_buffer].erase(bytes_transferred);
|
||||
|
||||
assert(int(m_send_buffer[sending_buffer].size()) >= m_write_pos);
|
||||
if (int(m_send_buffer[sending_buffer].size()) == m_write_pos)
|
||||
{
|
||||
m_send_buffer[sending_buffer].clear();
|
||||
m_write_pos = 0;
|
||||
}
|
||||
|
||||
m_last_sent = second_clock::universal_time();
|
||||
|
||||
on_sent(error, bytes_transferred);
|
||||
fill_send_buffer();
|
||||
if (!m_send_buffer[sending_buffer].empty())
|
||||
{
|
||||
// if the send operation didn't send all of the data in the buffer.
|
||||
// send it again.
|
||||
m_current_send_buffer = sending_buffer;
|
||||
}
|
||||
setup_send();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
|
@ -1930,6 +1954,9 @@ namespace libtorrent
|
|||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
assert(m_write_pos <= m_send_buffer[
|
||||
(m_current_send_buffer + 1) & 1].size());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue