*** empty log message ***
This commit is contained in:
parent
99db2c6395
commit
cfe5da0588
|
@ -189,8 +189,8 @@ int main(int argc, char* argv[])
|
|||
std::vector<torrent_handle> handles;
|
||||
session ses(6881);
|
||||
|
||||
// limit upload rate to 100 kB/s
|
||||
ses.set_upload_rate_limit(100 * 1024);
|
||||
// limit global upload rate to 30 kB/s
|
||||
ses.set_upload_rate_limit(30 * 1024);
|
||||
ses.set_http_settings(settings);
|
||||
ses.set_severity_level(alert::debug);
|
||||
|
||||
|
@ -216,7 +216,7 @@ int main(int argc, char* argv[])
|
|||
{}
|
||||
|
||||
handles.push_back(ses.add_torrent(t, "", resume_data));
|
||||
handles.back().set_max_uploads(40);
|
||||
handles.back().set_max_uploads(7);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
|
|
|
@ -59,18 +59,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
// a chance to request another block instead.
|
||||
// Where it also could become not-interested.
|
||||
|
||||
// TODO: maybe there should be some kind of
|
||||
// per-torrent free-upload counter. All free
|
||||
// download we get is put in there and increases
|
||||
// the amount of free upload we give. The free upload
|
||||
// could be distributed to the interest peers
|
||||
// depending on amount we have downloaded from
|
||||
// the peer and depending on the share ratio.
|
||||
// there's no point in giving free upload to
|
||||
// peers we can trade with. Maybe the free upload
|
||||
// only should be given to those we are not interested
|
||||
// in?
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
class torrent;
|
||||
|
@ -138,23 +126,6 @@ namespace libtorrent
|
|||
protocol_error(const std::string& msg): std::runtime_error(msg) {};
|
||||
};
|
||||
|
||||
struct chat_message_alert: alert
|
||||
{
|
||||
chat_message_alert(const torrent_handle& h
|
||||
, const peer_id& send
|
||||
, const std::string& msg)
|
||||
: alert(alert::critical, msg)
|
||||
, handle(h)
|
||||
, sender(send)
|
||||
{}
|
||||
|
||||
virtual std::auto_ptr<alert> clone() const
|
||||
{ return std::auto_ptr<alert>(new chat_message_alert(*this)); }
|
||||
|
||||
torrent_handle handle;
|
||||
peer_id sender;
|
||||
};
|
||||
|
||||
struct peer_request
|
||||
{
|
||||
int piece;
|
||||
|
@ -179,6 +150,46 @@ namespace libtorrent
|
|||
int full_block_bytes;
|
||||
};
|
||||
|
||||
struct chat_message_alert: alert
|
||||
{
|
||||
chat_message_alert(
|
||||
const torrent_handle& h
|
||||
, const peer_id& send
|
||||
, const std::string& msg)
|
||||
: alert(alert::critical, msg)
|
||||
, handle(h)
|
||||
, sender(send)
|
||||
{}
|
||||
|
||||
virtual std::auto_ptr<alert> clone() const
|
||||
{ return std::auto_ptr<alert>(new chat_message_alert(*this)); }
|
||||
|
||||
torrent_handle handle;
|
||||
peer_id sender;
|
||||
};
|
||||
|
||||
// TODO: document
|
||||
struct invalid_request_alert: alert
|
||||
{
|
||||
invalid_request_alert(
|
||||
const peer_request& r
|
||||
, const torrent_handle& h
|
||||
, const peer_id& send
|
||||
, const std::string& msg)
|
||||
: alert(alert::debug, msg)
|
||||
, handle(h)
|
||||
, sender(send)
|
||||
, request(r)
|
||||
{}
|
||||
|
||||
virtual std::auto_ptr<alert> clone() const
|
||||
{ return std::auto_ptr<alert>(new invalid_request_alert(*this)); }
|
||||
|
||||
torrent_handle handle;
|
||||
peer_id sender;
|
||||
peer_request request;
|
||||
};
|
||||
|
||||
class peer_connection: public boost::noncopyable
|
||||
{
|
||||
public:
|
||||
|
@ -259,6 +270,8 @@ namespace libtorrent
|
|||
// which torrent it should be associated with
|
||||
torrent* associated_torrent() const throw() { return m_attached_to_torrent?m_torrent:0; }
|
||||
|
||||
bool verify_piece(const peer_request& p) const;
|
||||
|
||||
const stat& statistics() const { return m_statistics; }
|
||||
|
||||
// is called once every second by the main loop
|
||||
|
|
|
@ -246,6 +246,22 @@ namespace libtorrent
|
|||
send_buffer_updated();
|
||||
}
|
||||
|
||||
// verifies a piece to see if it is valid (is within a valid range)
|
||||
// and if it can correspond to a request generated by libtorrent.
|
||||
bool peer_connection::verify_piece(const peer_request& p) const
|
||||
{
|
||||
return p.piece >= 0
|
||||
&& p.piece < m_torrent->torrent_file().num_pieces()
|
||||
&& p.length > 0
|
||||
&& p.start >= 0
|
||||
&& (p.length == m_torrent->block_size()
|
||||
|| (p.length < m_torrent->block_size()
|
||||
&& p.piece == m_torrent->torrent_file().num_pieces()-1
|
||||
&& p.start + p.length == m_torrent->torrent_file().piece_size(p.piece)))
|
||||
&& p.start + p.length <= m_torrent->torrent_file().piece_size(p.piece)
|
||||
&& p.start % m_torrent->block_size() == 0;
|
||||
}
|
||||
|
||||
boost::optional<piece_block_progress> peer_connection::downloading_piece() const
|
||||
{
|
||||
// are we currently receiving a 'piece' message?
|
||||
|
@ -255,26 +271,21 @@ namespace libtorrent
|
|||
return boost::optional<piece_block_progress>();
|
||||
|
||||
const char* ptr = &m_recv_buffer[1];
|
||||
int piece_index = detail::read_int(ptr);
|
||||
int offset = detail::read_int(ptr);
|
||||
int len = m_packet_size - 9;
|
||||
peer_request r;
|
||||
r.piece = detail::read_int(ptr);
|
||||
r.start = detail::read_int(ptr);
|
||||
r.length = m_packet_size - 9;
|
||||
|
||||
// is any of the piece message header data invalid?
|
||||
// TODO: make sure that len is == block_size or less only
|
||||
// if its's the last block.
|
||||
if (piece_index < 0
|
||||
|| piece_index >= m_torrent->torrent_file().num_pieces()
|
||||
|| offset < 0
|
||||
|| offset + len > m_torrent->torrent_file().piece_size(piece_index)
|
||||
|| offset % m_torrent->block_size() != 0)
|
||||
if (!verify_piece(r))
|
||||
return boost::optional<piece_block_progress>();
|
||||
|
||||
piece_block_progress p;
|
||||
|
||||
p.piece_index = piece_index;
|
||||
p.block_index = offset / m_torrent->block_size();
|
||||
p.piece_index = r.piece;
|
||||
p.block_index = r.start / m_torrent->block_size();
|
||||
p.bytes_downloaded = m_recv_pos - 9;
|
||||
p.full_block_bytes = len;
|
||||
p.full_block_bytes = r.length;
|
||||
|
||||
return boost::optional<piece_block_progress>(p);
|
||||
}
|
||||
|
@ -376,6 +387,7 @@ namespace libtorrent
|
|||
|
||||
void peer_connection::on_have(int received)
|
||||
{
|
||||
// TODO: if we're a seed, and this peer becomes a seed, disconnect
|
||||
if (m_packet_size != 5)
|
||||
throw protocol_error("'have' message size != 5");
|
||||
m_statistics.received_bytes(0, received);
|
||||
|
@ -454,11 +466,19 @@ namespace libtorrent
|
|||
interesting = true;
|
||||
}
|
||||
|
||||
if (piece_list.empty())
|
||||
if (piece_list.size() == m_have_piece.size())
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
(*m_logger) << m_socket->sender().as_string() << " *** THIS IS A SEED ***\n";
|
||||
(*m_logger) << " *** THIS IS A SEED ***\n";
|
||||
#endif
|
||||
// if we're a seed too, disconnect
|
||||
if (m_torrent->is_seed())
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
(*m_logger) << " we're also a seed, disconnecting\n";
|
||||
#endif
|
||||
throw network_error(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (interesting) m_torrent->get_policy().peer_is_interesting(*this);
|
||||
|
@ -514,7 +534,14 @@ namespace libtorrent
|
|||
"t: " << (int)m_torrent->torrent_file().piece_size(r.piece) << " | "
|
||||
"n: " << m_torrent->torrent_file().num_pieces() << " ]\n";
|
||||
#endif
|
||||
// TODO: log this illegal request
|
||||
if (m_torrent->alerts().should_post(alert::debug))
|
||||
{
|
||||
m_torrent->alerts().post_alert(invalid_request_alert(
|
||||
r
|
||||
, m_torrent->get_handle()
|
||||
, m_peer_id
|
||||
, "peer sent an illegal request, ignoring"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -524,6 +551,8 @@ namespace libtorrent
|
|||
|
||||
void peer_connection::on_piece(int received)
|
||||
{
|
||||
// classify the received data as protocol chatter
|
||||
// or data payload for the statistics
|
||||
if (m_recv_pos <= 9)
|
||||
// only received protocol data
|
||||
m_statistics.received_bytes(0, received);
|
||||
|
@ -544,66 +573,29 @@ namespace libtorrent
|
|||
if (m_recv_pos < m_packet_size) return;
|
||||
|
||||
const char* ptr = &m_recv_buffer[1];
|
||||
int index = detail::read_int(ptr);
|
||||
if (index < 0 || index >= m_torrent->torrent_file().num_pieces())
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
(*m_logger) << m_socket->sender().as_string() << " piece index invalid\n";
|
||||
#endif
|
||||
throw protocol_error("invalid piece index in piece message");
|
||||
}
|
||||
int offset = detail::read_int(ptr);
|
||||
int len = m_packet_size - 9;
|
||||
peer_request p;
|
||||
p.piece = detail::read_int(ptr);
|
||||
p.start = detail::read_int(ptr);
|
||||
p.length = m_packet_size - 9;
|
||||
|
||||
if (offset < 0)
|
||||
if (!verify_piece(p))
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
(*m_logger) << m_socket->sender().as_string() << " offset < 0\n";
|
||||
(*m_logger) << " <== INVALID_PIECE [ piece: " << p.piece << " | "
|
||||
"start: " << p.start << " | "
|
||||
"length: " << p.length << " ]\n";
|
||||
#endif
|
||||
throw protocol_error("offset < 0 in piece message");
|
||||
throw protocol_error("invalid piece packet");
|
||||
}
|
||||
|
||||
if (offset + len > m_torrent->torrent_file().piece_size(index))
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
(*m_logger) << m_socket->sender().as_string() << " piece packet contains more data than the piece size\n";
|
||||
#endif
|
||||
throw protocol_error("piece message contains more data than the piece size");
|
||||
}
|
||||
// TODO: make sure that len is == block_size or less only
|
||||
// if its's the last block.
|
||||
|
||||
if (offset % m_torrent->block_size() != 0)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
(*m_logger) << m_socket->sender().as_string() << " piece packet contains unaligned offset\n";
|
||||
#endif
|
||||
throw protocol_error("piece message contains unaligned offset");
|
||||
}
|
||||
/*
|
||||
piece_block req = m_download_queue.front();
|
||||
if (req.piece_index != index)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
(*m_logger) << m_socket->sender().as_string() << " piece packet contains unrequested index\n";
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if (req.block_index != offset / m_torrent->block_size())
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
(*m_logger) << m_socket->sender().as_string() << " piece packet contains unrequested offset\n";
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
#ifndef NDEBUG
|
||||
(*m_logger) << m_socket->sender().as_string() << " <== PIECE [ piece: " << index << " | s: " << offset << " | l: " << len << " ]\n";
|
||||
(*m_logger) << " <== PIECE [ piece: " << p.piece << " | "
|
||||
"s: " << p.start << " | "
|
||||
"l: " << p.length << " ]\n";
|
||||
#endif
|
||||
|
||||
piece_picker& picker = m_torrent->picker();
|
||||
piece_block block_finished(index, offset / m_torrent->block_size());
|
||||
piece_block block_finished(p.piece, p.start / m_torrent->block_size());
|
||||
|
||||
std::deque<piece_block>::iterator b
|
||||
= std::find(
|
||||
|
@ -626,25 +618,25 @@ namespace libtorrent
|
|||
// if the block we got is already finished, then ignore it
|
||||
if (picker.is_finished(block_finished)) return;
|
||||
|
||||
m_torrent->filesystem().write(&m_recv_buffer[9], index, offset, len);
|
||||
m_torrent->filesystem().write(&m_recv_buffer[9], p.piece, p.start, p.length);
|
||||
|
||||
picker.mark_as_finished(block_finished, m_peer_id);
|
||||
|
||||
m_torrent->get_policy().block_finished(*this, block_finished);
|
||||
|
||||
// did we just finish the piece?
|
||||
if (picker.is_piece_finished(index))
|
||||
if (picker.is_piece_finished(p.piece))
|
||||
{
|
||||
bool verified = m_torrent->verify_piece(index);
|
||||
bool verified = m_torrent->verify_piece(p.piece);
|
||||
if (verified)
|
||||
{
|
||||
m_torrent->announce_piece(index);
|
||||
m_torrent->announce_piece(p.piece);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_torrent->piece_failed(index);
|
||||
m_torrent->piece_failed(p.piece);
|
||||
}
|
||||
m_torrent->get_policy().piece_finished(index, verified);
|
||||
m_torrent->get_policy().piece_finished(p.piece, verified);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -711,12 +703,6 @@ namespace libtorrent
|
|||
m_extension_messages[i] = f->second.integer();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: temporary
|
||||
// if (m_extension_messages[extended_chat_message] != -1)
|
||||
// {
|
||||
// send_chat_message("Hi, this is a test chat message");
|
||||
// }
|
||||
}
|
||||
catch(invalid_encoding& e)
|
||||
{
|
||||
|
@ -869,6 +855,7 @@ namespace libtorrent
|
|||
send_buffer_updated();
|
||||
}
|
||||
|
||||
// TODO: should this be renamed to 'send_request()'?
|
||||
void peer_connection::request_block(piece_block block)
|
||||
{
|
||||
assert(block.piece_index >= 0);
|
||||
|
@ -905,6 +892,12 @@ namespace libtorrent
|
|||
|
||||
#ifndef NDEBUG
|
||||
(*m_logger) << " ==> REQUEST [ piece: " << block.piece_index << " | s: " << block_offset << " | l: " << block_size << " | " << block.block_index << " ]\n";
|
||||
|
||||
peer_request r;
|
||||
r.piece = block.piece_index;
|
||||
r.start = block_offset;
|
||||
r.length = block_size;
|
||||
assert(verify_piece(r));
|
||||
#endif
|
||||
|
||||
send_buffer_updated();
|
||||
|
@ -1029,6 +1022,10 @@ namespace libtorrent
|
|||
|
||||
void peer_connection::send_have(int index)
|
||||
{
|
||||
// optimization, don't send have messages
|
||||
// to peers that already have the piece
|
||||
if (m_have_piece[index]) return;
|
||||
|
||||
const int packet_size = 9;
|
||||
char msg[packet_size] = {0,0,0,5,msg_have};
|
||||
char* ptr = msg+5;
|
||||
|
|
|
@ -247,24 +247,6 @@ namespace
|
|||
namespace libtorrent
|
||||
{
|
||||
/*
|
||||
TODO: make two proxy classes that filter out
|
||||
all unneccesary members from torrent and peer_connection
|
||||
to make it easier to use them in the policy
|
||||
|
||||
useful member functions:
|
||||
|
||||
void torrent::connect_to_peer(address, peer_id);
|
||||
piece_picker& torrent::picker();
|
||||
std::vector<peer_connection*>::const_iterator torrent::begin() const
|
||||
std::vector<peer_connection*>::const_iterator torrent::end() const
|
||||
|
||||
void peer_connection::interested();
|
||||
void peer_connection::not_interested();
|
||||
void peer_connection::choke();
|
||||
void peer_connection::unchoke();
|
||||
void peer_connection::request_piece(int index);
|
||||
const std::vector<int>& peer_connection::download_queue();
|
||||
|
||||
TODO: implement some kind of limit of the number of sockets
|
||||
opened, to use for systems where a user has a limited number
|
||||
of open file descriptors. and for windows which has a buggy tcp-stack.
|
||||
|
@ -565,8 +547,6 @@ namespace libtorrent
|
|||
i->connection->not_interested();
|
||||
}
|
||||
}
|
||||
// TODO: if verification failed, mark the peers that were involved
|
||||
// in some way
|
||||
}
|
||||
|
||||
// TODO: we must be able to get interested
|
||||
|
|
|
@ -63,8 +63,6 @@ namespace std
|
|||
};
|
||||
#endif
|
||||
|
||||
// TODO: enable floating point exceptions in debug mode!
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
@ -886,7 +884,6 @@ namespace libtorrent
|
|||
m_impl.m_alerts.set_severity(s);
|
||||
}
|
||||
|
||||
// TODO: store resume data as an entry instead
|
||||
void detail::piece_checker_data::parse_resume_data(
|
||||
const entry& resume_data
|
||||
, const torrent_info& info)
|
||||
|
|
Loading…
Reference in New Issue