*** empty log message ***
This commit is contained in:
@@ -189,8 +189,8 @@ int main(int argc, char* argv[])
|
|||||||
std::vector<torrent_handle> handles;
|
std::vector<torrent_handle> handles;
|
||||||
session ses(6881);
|
session ses(6881);
|
||||||
|
|
||||||
// limit upload rate to 100 kB/s
|
// limit global upload rate to 30 kB/s
|
||||||
ses.set_upload_rate_limit(100 * 1024);
|
ses.set_upload_rate_limit(30 * 1024);
|
||||||
ses.set_http_settings(settings);
|
ses.set_http_settings(settings);
|
||||||
ses.set_severity_level(alert::debug);
|
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.push_back(ses.add_torrent(t, "", resume_data));
|
||||||
handles.back().set_max_uploads(40);
|
handles.back().set_max_uploads(7);
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
|
@@ -59,18 +59,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
// a chance to request another block instead.
|
// a chance to request another block instead.
|
||||||
// Where it also could become not-interested.
|
// 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
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
class torrent;
|
class torrent;
|
||||||
@@ -138,23 +126,6 @@ namespace libtorrent
|
|||||||
protocol_error(const std::string& msg): std::runtime_error(msg) {};
|
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
|
struct peer_request
|
||||||
{
|
{
|
||||||
int piece;
|
int piece;
|
||||||
@@ -179,6 +150,46 @@ namespace libtorrent
|
|||||||
int full_block_bytes;
|
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
|
class peer_connection: public boost::noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -259,6 +270,8 @@ namespace libtorrent
|
|||||||
// which torrent it should be associated with
|
// which torrent it should be associated with
|
||||||
torrent* associated_torrent() const throw() { return m_attached_to_torrent?m_torrent:0; }
|
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; }
|
const stat& statistics() const { return m_statistics; }
|
||||||
|
|
||||||
// is called once every second by the main loop
|
// is called once every second by the main loop
|
||||||
|
@@ -246,6 +246,22 @@ namespace libtorrent
|
|||||||
send_buffer_updated();
|
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
|
boost::optional<piece_block_progress> peer_connection::downloading_piece() const
|
||||||
{
|
{
|
||||||
// are we currently receiving a 'piece' message?
|
// are we currently receiving a 'piece' message?
|
||||||
@@ -255,26 +271,21 @@ namespace libtorrent
|
|||||||
return boost::optional<piece_block_progress>();
|
return boost::optional<piece_block_progress>();
|
||||||
|
|
||||||
const char* ptr = &m_recv_buffer[1];
|
const char* ptr = &m_recv_buffer[1];
|
||||||
int piece_index = detail::read_int(ptr);
|
peer_request r;
|
||||||
int offset = detail::read_int(ptr);
|
r.piece = detail::read_int(ptr);
|
||||||
int len = m_packet_size - 9;
|
r.start = detail::read_int(ptr);
|
||||||
|
r.length = m_packet_size - 9;
|
||||||
|
|
||||||
// is any of the piece message header data invalid?
|
// is any of the piece message header data invalid?
|
||||||
// TODO: make sure that len is == block_size or less only
|
if (!verify_piece(r))
|
||||||
// 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)
|
|
||||||
return boost::optional<piece_block_progress>();
|
return boost::optional<piece_block_progress>();
|
||||||
|
|
||||||
piece_block_progress p;
|
piece_block_progress p;
|
||||||
|
|
||||||
p.piece_index = piece_index;
|
p.piece_index = r.piece;
|
||||||
p.block_index = offset / m_torrent->block_size();
|
p.block_index = r.start / m_torrent->block_size();
|
||||||
p.bytes_downloaded = m_recv_pos - 9;
|
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);
|
return boost::optional<piece_block_progress>(p);
|
||||||
}
|
}
|
||||||
@@ -376,6 +387,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
void peer_connection::on_have(int received)
|
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)
|
if (m_packet_size != 5)
|
||||||
throw protocol_error("'have' message size != 5");
|
throw protocol_error("'have' message size != 5");
|
||||||
m_statistics.received_bytes(0, received);
|
m_statistics.received_bytes(0, received);
|
||||||
@@ -454,11 +466,19 @@ namespace libtorrent
|
|||||||
interesting = true;
|
interesting = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (piece_list.empty())
|
if (piece_list.size() == m_have_piece.size())
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
(*m_logger) << m_socket->sender().as_string() << " *** THIS IS A SEED ***\n";
|
(*m_logger) << " *** THIS IS A SEED ***\n";
|
||||||
#endif
|
#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);
|
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) << " | "
|
"t: " << (int)m_torrent->torrent_file().piece_size(r.piece) << " | "
|
||||||
"n: " << m_torrent->torrent_file().num_pieces() << " ]\n";
|
"n: " << m_torrent->torrent_file().num_pieces() << " ]\n";
|
||||||
#endif
|
#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)
|
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)
|
if (m_recv_pos <= 9)
|
||||||
// only received protocol data
|
// only received protocol data
|
||||||
m_statistics.received_bytes(0, received);
|
m_statistics.received_bytes(0, received);
|
||||||
@@ -544,66 +573,29 @@ namespace libtorrent
|
|||||||
if (m_recv_pos < m_packet_size) return;
|
if (m_recv_pos < m_packet_size) return;
|
||||||
|
|
||||||
const char* ptr = &m_recv_buffer[1];
|
const char* ptr = &m_recv_buffer[1];
|
||||||
int index = detail::read_int(ptr);
|
peer_request p;
|
||||||
if (index < 0 || index >= m_torrent->torrent_file().num_pieces())
|
p.piece = detail::read_int(ptr);
|
||||||
{
|
p.start = detail::read_int(ptr);
|
||||||
#ifndef NDEBUG
|
p.length = m_packet_size - 9;
|
||||||
(*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;
|
|
||||||
|
|
||||||
if (offset < 0)
|
if (!verify_piece(p))
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
#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
|
#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
|
#ifndef NDEBUG
|
||||||
(*m_logger) << m_socket->sender().as_string() << " piece packet contains more data than the piece size\n";
|
(*m_logger) << " <== PIECE [ piece: " << p.piece << " | "
|
||||||
#endif
|
"s: " << p.start << " | "
|
||||||
throw protocol_error("piece message contains more data than the piece size");
|
"l: " << p.length << " ]\n";
|
||||||
}
|
|
||||||
// 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";
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
piece_picker& picker = m_torrent->picker();
|
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::deque<piece_block>::iterator b
|
||||||
= std::find(
|
= std::find(
|
||||||
@@ -626,25 +618,25 @@ namespace libtorrent
|
|||||||
// if the block we got is already finished, then ignore it
|
// if the block we got is already finished, then ignore it
|
||||||
if (picker.is_finished(block_finished)) return;
|
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);
|
picker.mark_as_finished(block_finished, m_peer_id);
|
||||||
|
|
||||||
m_torrent->get_policy().block_finished(*this, block_finished);
|
m_torrent->get_policy().block_finished(*this, block_finished);
|
||||||
|
|
||||||
// did we just finish the piece?
|
// 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)
|
if (verified)
|
||||||
{
|
{
|
||||||
m_torrent->announce_piece(index);
|
m_torrent->announce_piece(p.piece);
|
||||||
}
|
}
|
||||||
else
|
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();
|
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)
|
catch(invalid_encoding& e)
|
||||||
{
|
{
|
||||||
@@ -869,6 +855,7 @@ namespace libtorrent
|
|||||||
send_buffer_updated();
|
send_buffer_updated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: should this be renamed to 'send_request()'?
|
||||||
void peer_connection::request_block(piece_block block)
|
void peer_connection::request_block(piece_block block)
|
||||||
{
|
{
|
||||||
assert(block.piece_index >= 0);
|
assert(block.piece_index >= 0);
|
||||||
@@ -905,6 +892,12 @@ namespace libtorrent
|
|||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
(*m_logger) << " ==> REQUEST [ piece: " << block.piece_index << " | s: " << block_offset << " | l: " << block_size << " | " << block.block_index << " ]\n";
|
(*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
|
#endif
|
||||||
|
|
||||||
send_buffer_updated();
|
send_buffer_updated();
|
||||||
@@ -1029,6 +1022,10 @@ namespace libtorrent
|
|||||||
|
|
||||||
void peer_connection::send_have(int index)
|
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;
|
const int packet_size = 9;
|
||||||
char msg[packet_size] = {0,0,0,5,msg_have};
|
char msg[packet_size] = {0,0,0,5,msg_have};
|
||||||
char* ptr = msg+5;
|
char* ptr = msg+5;
|
||||||
|
@@ -247,24 +247,6 @@ namespace
|
|||||||
namespace libtorrent
|
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
|
TODO: implement some kind of limit of the number of sockets
|
||||||
opened, to use for systems where a user has a limited number
|
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.
|
of open file descriptors. and for windows which has a buggy tcp-stack.
|
||||||
@@ -565,8 +547,6 @@ namespace libtorrent
|
|||||||
i->connection->not_interested();
|
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
|
// TODO: we must be able to get interested
|
||||||
|
@@ -63,8 +63,6 @@ namespace std
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: enable floating point exceptions in debug mode!
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -886,7 +884,6 @@ namespace libtorrent
|
|||||||
m_impl.m_alerts.set_severity(s);
|
m_impl.m_alerts.set_severity(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: store resume data as an entry instead
|
|
||||||
void detail::piece_checker_data::parse_resume_data(
|
void detail::piece_checker_data::parse_resume_data(
|
||||||
const entry& resume_data
|
const entry& resume_data
|
||||||
, const torrent_info& info)
|
, const torrent_info& info)
|
||||||
|
Reference in New Issue
Block a user