fixed a serious bug where corrupt messages could be sent out.

This commit is contained in:
Arvid Norberg 2006-04-30 00:39:18 +00:00
parent d1c33c0d2b
commit 18cb6736ea
7 changed files with 85 additions and 33 deletions

View File

@ -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
{

View File

@ -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;

View File

@ -60,8 +60,6 @@ namespace libtorrent
{
assert(given <= max);
assert(given >= min);
// TODO: TEMP!
// assert(given >= used);
return given - used;
}

View File

@ -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;
};
}

View File

@ -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)

View File

@ -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

View File

@ -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