From cfe5da0588cc9ce7402b7e73ee8f6d7490548442 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Thu, 8 Jan 2004 13:03:38 +0000 Subject: [PATCH] *** empty log message *** --- examples/client_test.cpp | 6 +- include/libtorrent/peer_connection.hpp | 71 +++++++----- src/peer_connection.cpp | 153 ++++++++++++------------- src/policy.cpp | 20 ---- src/session.cpp | 3 - 5 files changed, 120 insertions(+), 133 deletions(-) diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 806ef8068..f0da0d916 100755 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -189,8 +189,8 @@ int main(int argc, char* argv[]) std::vector 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) { diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index 5164066af..fa23fd7c1 100755 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -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 clone() const - { return std::auto_ptr(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 clone() const + { return std::auto_ptr(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 clone() const + { return std::auto_ptr(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 diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 2f9389224..b92de0c17 100755 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -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 peer_connection::downloading_piece() const { // are we currently receiving a 'piece' message? @@ -255,26 +271,21 @@ namespace libtorrent return boost::optional(); 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 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(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::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; diff --git a/src/policy.cpp b/src/policy.cpp index b6715c40e..5ef57ce75 100755 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -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::const_iterator torrent::begin() const - std::vector::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& 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 diff --git a/src/session.cpp b/src/session.cpp index d44639ab5..596941653 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -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)