*** empty log message ***

This commit is contained in:
Arvid Norberg 2004-09-12 13:53:00 +00:00
parent 492565b979
commit 2406d5e54d
7 changed files with 164 additions and 52 deletions

View File

@ -55,7 +55,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/identify_client.hpp"
#include "libtorrent/alert_types.hpp"
#ifdef WIN32
#ifdef _WIN32
#if defined(_MSC_VER)
# define for if (false) {} else for

View File

@ -224,6 +224,8 @@ namespace libtorrent
bool supports_extension(extension_index ex) const
{ return m_extension_messages[ex] != -1; }
bool has_metadata() const;
// the message handlers are called
// each time a recv() returns some new
// data, the last time it will be called
@ -264,8 +266,8 @@ namespace libtorrent
void send_handshake();
void send_extensions();
void send_chat_message(const std::string& msg);
void send_metadata(int start, int size);
void send_metadata_request(int start, int size);
void send_metadata(std::pair<int, int> req);
void send_metadata_request(std::pair<int, int> req);
// how much bandwidth we're using, how much we want,
// and how much we are allowed to use.
@ -511,6 +513,10 @@ namespace libtorrent
// request to this peer, and reset to false when
// we receive a reply to our request.
bool m_waiting_metadata_request;
// if we're waiting for a metadata request
// this was the request we sent
std::pair<int, int> m_last_metadata_request;
};
}

View File

@ -79,6 +79,10 @@ namespace libtorrent
struct piece_checker_data;
}
int div_round_up(int numerator, int denominator);
std::pair<int, int> req_to_offset(std::pair<int, int> req, int total_size);
std::pair<int, int> offset_to_req(std::pair<int, int> offset, int total_size);
// a torrent is a class that holds information
// for a specific download. It updates itself against
// the tracker
@ -344,6 +348,7 @@ namespace libtorrent
// returns a range of the metadata that
// we should request.
std::pair<int, int> metadata_request();
void cancel_metadata_request(std::pair<int, int> req);
private:

View File

@ -161,7 +161,8 @@ namespace libtorrent
m_send_buffer += key_string.str();
m_send_buffer += "&compact=1";
m_send_buffer += "&numwant=";
m_send_buffer += boost::lexical_cast<std::string>(req.num_want);
m_send_buffer += boost::lexical_cast<std::string>(
std::min(req.num_want, 999));
// extension that tells the tracker that
// we don't need any peer_id's in the response

View File

@ -1205,7 +1205,7 @@ namespace libtorrent
throw protocol_error("invalid metadata request");
}
send_metadata(start, size);
send_metadata(std::make_pair(start, size));
}
break;
case 1: // data
@ -1221,12 +1221,22 @@ namespace libtorrent
if (offset + data_size > total_size)
throw protocol_error("invalid metadata message");
#ifndef NDEBUG
using namespace boost::posix_time;
(*m_logger) << to_simple_string(second_clock::local_time())
<< " <== METADATA [ tot: " << total_size << " offset: "
<< offset << " size: " << data_size << " ]\n";
#endif
m_waiting_metadata_request = false;
m_torrent->received_metadata(&m_recv_buffer[5+9], data_size, offset, total_size);
}
break;
case 2: // have no data
m_no_metadata = boost::posix_time::second_clock::local_time();
if (m_waiting_metadata_request)
m_torrent->cancel_metadata_request(m_last_metadata_request);
m_waiting_metadata_request = false;
break;
}
@ -1276,6 +1286,12 @@ namespace libtorrent
m_torrent->get_policy().peer_from_tracker(adr, m_peer_id);
}
bool peer_connection::has_metadata() const
{
using namespace boost::posix_time;
return second_clock::local_time() - m_no_metadata > minutes(5);
}
void peer_connection::disconnect()
{
@ -1427,11 +1443,12 @@ namespace libtorrent
send_buffer_updated();
}
void peer_connection::send_metadata(int start, int size)
void peer_connection::send_metadata(std::pair<int, int> req)
{
assert(start >= 0);
assert(size > 0);
assert(start + size <= 256);
assert(req.first >= 0);
assert(req.second > 0);
assert(req.second <= 256);
assert(req.first + req.second <= 256);
assert(m_torrent);
INVARIANT_CHECK;
@ -1442,21 +1459,20 @@ namespace libtorrent
if (m_torrent->valid_metadata())
{
int offset = start * (int)m_torrent->metadata().size() / 256;
int metadata_size
= (start + size) * (int)m_torrent->metadata().size() / 256 - offset;
std::pair<int, int> offset
= req_to_offset(req, (int)m_torrent->metadata().size());
// yes, we have metadata, send it
assert(size <= (int)m_torrent->metadata().size());
detail::write_uint32(5 + 9 + metadata_size, ptr);
detail::write_uint32(5 + 9 + offset.second, ptr);
detail::write_uint8(msg_extended, ptr);
detail::write_int32(m_extension_messages[extended_metadata_message], ptr);
// means 'data packet'
detail::write_uint8(1, ptr);
detail::write_uint32((int)m_torrent->metadata().size(), ptr);
detail::write_uint32(offset, ptr);
detail::write_uint32(offset.first, ptr);
std::vector<char> const& metadata = m_torrent->metadata();
std::copy(&metadata[offset], &metadata[offset + metadata_size], ptr);
std::copy(&metadata[offset.first], &metadata[offset.first
+ offset.second], ptr);
}
else
{
@ -1471,18 +1487,28 @@ namespace libtorrent
send_buffer_updated();
}
void peer_connection::send_metadata_request(int start, int size)
void peer_connection::send_metadata_request(std::pair<int, int> req)
{
assert(start >= 0);
assert(size > 0);
assert(start + size <= 256);
assert(req.first >= 0);
assert(req.second > 0);
assert(req.first + req.second <= 256);
assert(m_torrent);
assert(!m_torrent->valid_metadata());
INVARIANT_CHECK;
int start = req.first;
int size = req.second;
// abort if the peer doesn't support the metadata extension
if (!supports_extension(extended_metadata_message)) return;
#ifndef NDEBUG
using namespace boost::posix_time;
(*m_logger) << to_simple_string(second_clock::local_time())
<< " ==> METADATA_REQUEST [ start: " << req.first
<< " size: " << req.second << " ]\n";
#endif
std::back_insert_iterator<std::vector<char> > ptr(m_send_buffer);
detail::write_uint32(1 + 4 + 3, ptr);
@ -1690,19 +1716,19 @@ namespace libtorrent
// if we don't have any metadata, and this peer
// supports the request metadata extension
// and we aren't currently waiting for a request
// reply.
// reply. Then, send a request for some metadata.
if (!m_torrent->valid_metadata()
&& supports_extension(extended_metadata_message)
&& !m_waiting_metadata_request)
&& !m_waiting_metadata_request
&& has_metadata())
{
assert(m_torrent);
std::pair<int, int> req = m_torrent->metadata_request();
send_metadata_request(req.first, req.second);
m_last_metadata_request = m_torrent->metadata_request();
send_metadata_request(m_last_metadata_request);
m_waiting_metadata_request = true;
m_metadata_request = boost::posix_time::second_clock::local_time();
}
m_statistics.second_tick();
m_ul_bandwidth_quota.used = std::min(
(int)ceil(statistics().upload_rate())

View File

@ -995,12 +995,11 @@ namespace libtorrent
// first, create all missing directories
for (torrent_info::file_iterator file_iter = m_info.begin_files(),
end_iter = m_info.end_files();
file_iter != end_iter;
++file_iter)
end_iter = m_info.end_files(); file_iter != end_iter; ++file_iter)
{
fs::path dir = m_save_path / get_filename(m_info, file_iter->path);
fs::create_directories(dir.branch_path());
if (!fs::exists(dir.branch_path()))
fs::create_directories(dir.branch_path());
}
std::vector<char> piece_data(static_cast<int>(m_info.piece_length()));

View File

@ -501,7 +501,7 @@ namespace libtorrent
assert(!urls.empty());
m_trackers = urls;
if (m_currently_trying_tracker >= (int)m_trackers.size())
m_currently_trying_tracker = m_trackers.size()-1;
m_currently_trying_tracker = (int)m_trackers.size()-1;
m_last_working_tracker = -1;
}
@ -982,6 +982,43 @@ namespace libtorrent
boost::bind(&std::map<address,peer_connection*>::value_type::second, _1)));
}
int div_round_up(int numerator, int denominator)
{
return (numerator + denominator - 1) / denominator;
}
std::pair<int, int> req_to_offset(std::pair<int, int> req, int total_size)
{
assert(req.first >= 0);
assert(req.second > 0);
assert(req.second <= 256);
assert(req.first + req.second <= 256);
int start = div_round_up(req.first * total_size, 256);
int size = div_round_up((req.first + req.second) * total_size, 256) - start;
return std::make_pair(start, size);
}
std::pair<int, int> offset_to_req(std::pair<int, int> offset, int total_size)
{
int start = offset.first * 256 / total_size;
int size = (offset.first + offset.second) * 256 / total_size - start;
std::pair<int, int> ret(start, size);
assert(start >= 0);
assert(size > 0);
assert(start <= 256);
assert(start + size <= 256);
// assert the identity of this function
#ifndef NDEBUG
std::pair<int, int> identity = req_to_offset(ret, total_size);
assert(offset == identity);
#endif
return ret;
}
bool torrent::received_metadata(char const* buf, int size, int offset, int total_size)
{
INVARIANT_CHECK;
@ -997,28 +1034,19 @@ namespace libtorrent
, &m_metadata[offset]);
if (m_have_metadata.empty())
m_have_metadata.resize(255, false);
m_have_metadata.resize(256, false);
int start = offset * 255 / (int)m_metadata.size();
if ((offset * 255) % (int)m_metadata.size() != 0)
throw protocol_error("unaligned metadata message offset");
int block_size = size * (255 - offset) / (int)m_metadata.size() - start;
assert(start >= 0);
assert(block_size > 0);
assert(start < 256);
assert(start + block_size <= 256);
std::pair<int, int> req = offset_to_req(std::make_pair(offset, size), total_size);
std::fill(
m_have_metadata.begin() + start
, m_have_metadata.begin() + start + block_size
m_have_metadata.begin() + req.first
, m_have_metadata.begin() + req.first + req.second
, true);
bool have_all = std::count(
m_have_metadata.begin()
, m_have_metadata.end()
, true) == 255;
, true) == 256;
if (!have_all) return false;
@ -1030,7 +1058,7 @@ namespace libtorrent
{
std::fill(
m_have_metadata.begin()
, m_have_metadata.end() + start + block_size
, m_have_metadata.end() + req.first + req.second
, false);
return false;
}
@ -1055,8 +1083,9 @@ namespace libtorrent
// all peer connections have to initialize themselves now that the metadata
// is available
for (std::map<address, peer_connection*>::iterator i = m_connections.begin();
i != m_connections.end(); ++i)
typedef std::map<address, peer_connection*> conn_map;
for (conn_map::iterator i = m_connections.begin()
, end(m_connections.end()); i != end; ++i)
{
i->second->init();
}
@ -1074,17 +1103,63 @@ namespace libtorrent
std::pair<int, int> torrent::metadata_request()
{
// TODO: count the peers that supports the
// metadata extension
// check to see if we know how big the metadata
// is (if m_metadata.size() > 0)
std::pair<int, int> ret(0, 256);
// count the number of peers that supports the
// extension and that has metadata
int peers = 0;
typedef std::map<address, peer_connection*> conn_map;
for (conn_map::iterator i = m_connections.begin()
, end(m_connections.end()); i != end; ++i)
{
if (!i->second->supports_extension(
peer_connection::extended_metadata_message))
continue;
if (!i->second->has_metadata())
continue;
++peers;
}
// the number of blocks to request
int num_blocks = 256 / (peers + 1);
if (num_blocks < 1) num_blocks = 1;
assert(num_blocks <= 128);
int min_element = std::numeric_limits<int>::max();
int best_index = 0;
for (int i = 0; i < 256 - num_blocks + 1; ++i)
{
int min = *std::min_element(m_requested_metadata.begin() + i
, m_requested_metadata.begin() + i + num_blocks);
min += std::accumulate(m_requested_metadata.begin() + i
, m_requested_metadata.begin() + i + num_blocks, (int)0);
if (min_element > min)
{
best_index = i;
min_element = min;
}
}
std::pair<int, int> ret(best_index, num_blocks);
for (int i = ret.first; i < ret.first + ret.second; ++i)
m_requested_metadata[i]++;
assert(ret.first >= 0);
assert(ret.second > 0);
assert(ret.second <= 256);
assert(ret.first + ret.second <= 256);
return ret;
}
void torrent::cancel_metadata_request(std::pair<int, int> req)
{
for (int i = req.first; i < req.first + req.second; ++i)
{
assert(m_requested_metadata[i] > 0);
--m_requested_metadata[i];
}
}
void torrent::tracker_request_timed_out()
{
#ifndef NDEBUG