diff --git a/libtorrent/include/libtorrent/udp_socket.hpp b/libtorrent/include/libtorrent/udp_socket.hpp index 77eae5050..79b301b49 100644 --- a/libtorrent/include/libtorrent/udp_socket.hpp +++ b/libtorrent/include/libtorrent/udp_socket.hpp @@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include +#include namespace libtorrent { @@ -83,6 +84,9 @@ namespace libtorrent void wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec); void unwrap(error_code const& e, char const* buf, int size); + typedef boost::mutex mutex_t; + mutable mutex_t m_mutex; + udp::socket m_ipv4_sock; udp::socket m_ipv6_sock; udp::endpoint m_v4_ep; diff --git a/libtorrent/src/disk_io_thread.cpp b/libtorrent/src/disk_io_thread.cpp index dd9554d39..901834634 100644 --- a/libtorrent/src/disk_io_thread.cpp +++ b/libtorrent/src/disk_io_thread.cpp @@ -1061,6 +1061,7 @@ namespace libtorrent if (k->blocks[j] == 0) continue; free_buffer(k->blocks[j]); k->blocks[j] = 0; + --m_cache_stats.cache_size; } } m_pieces.erase(i, m_pieces.end()); diff --git a/libtorrent/src/peer_connection.cpp b/libtorrent/src/peer_connection.cpp index 5ce04bcf4..46cea6184 100755 --- a/libtorrent/src/peer_connection.cpp +++ b/libtorrent/src/peer_connection.cpp @@ -337,6 +337,12 @@ namespace libtorrent boost::shared_ptr t = m_torrent.lock(); TORRENT_ASSERT(t); + // if m_have_piece is 0, it means the connections + // have not been initialized yet. The interested + // flag will be updated once they are. + if (m_have_piece.size() == 0) return; + if (!t->ready_for_connections()) return; + bool interested = false; if (!t->is_finished()) { @@ -361,7 +367,7 @@ namespace libtorrent // may throw an asio error if socket has disconnected catch (std::exception&) {} - TORRENT_ASSERT(is_interesting() == interested); + TORRENT_ASSERT(in_handshake() || is_interesting() == interested); } #ifndef TORRENT_DISABLE_EXTENSIONS diff --git a/libtorrent/src/piece_picker.cpp b/libtorrent/src/piece_picker.cpp index 0c480cf25..35b97b4df 100755 --- a/libtorrent/src/piece_picker.cpp +++ b/libtorrent/src/piece_picker.cpp @@ -1517,6 +1517,7 @@ namespace libtorrent , end(m_downloads.end()); i != end; ++i) { if (!pieces[i->index]) continue; + if (piece_priority(i->index) == 0) continue; int num_blocks_in_piece = blocks_in_piece(i->index); @@ -1540,6 +1541,7 @@ namespace libtorrent , end(m_downloads.end()); i != end; ++i) { if (!pieces[i->index]) continue; + if (piece_priority(i->index) == 0) continue; int num_blocks_in_piece = blocks_in_piece(i->index); for (int j = 0; j < num_blocks_in_piece; ++j) diff --git a/libtorrent/src/storage.cpp b/libtorrent/src/storage.cpp index 750ecde1a..208c9d3c4 100755 --- a/libtorrent/src/storage.cpp +++ b/libtorrent/src/storage.cpp @@ -69,6 +69,8 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/aux_/session_impl.hpp" #include "libtorrent/disk_buffer_holder.hpp" +//#define TORRENT_PARTIAL_HASH_LOG + #ifndef NDEBUG #include #include @@ -453,12 +455,14 @@ namespace libtorrent sha1_hash storage::hash_for_slot(int slot, partial_hash& ph, int piece_size) { + TORRENT_ASSERT(!error()); #ifndef NDEBUG hasher partial; hasher whole; int slot_size1 = piece_size; m_scratch_buffer.resize(slot_size1); - read_impl(&m_scratch_buffer[0], slot, 0, slot_size1, true); + read_impl(&m_scratch_buffer[0], slot, 0, slot_size1, false); + if (error()) return sha1_hash(0); if (ph.offset > 0) partial.update(&m_scratch_buffer[0], ph.offset); whole.update(&m_scratch_buffer[0], slot_size1); @@ -469,7 +473,8 @@ namespace libtorrent if (slot_size > 0) { m_scratch_buffer.resize(slot_size); - read_impl(&m_scratch_buffer[0], slot, ph.offset, slot_size, true); + read_impl(&m_scratch_buffer[0], slot, ph.offset, slot_size, false); + if (error()) return sha1_hash(0); ph.h.update(&m_scratch_buffer[0], slot_size); } #ifndef NDEBUG @@ -1538,7 +1543,9 @@ namespace libtorrent // only save the partial hash if the write succeeds if (ret != size) return ret; -// std::ofstream out("partial_hash.log", std::ios::app); +#ifdef TORRENT_PARTIAL_HASH_LOG + std::ofstream out("partial_hash.log", std::ios::app); +#endif if (offset == 0) { @@ -1546,7 +1553,7 @@ namespace libtorrent TORRENT_ASSERT(ph.offset == 0); ph.offset = size; ph.h.update(buf, size); -/* +#ifdef TORRENT_PARTIAL_HASH_LOG out << time_now_string() << " NEW [" " s: " << this << " p: " << piece_index @@ -1554,7 +1561,7 @@ namespace libtorrent << " size: " << size << " entries: " << m_piece_hasher.size() << " ]" << std::endl; -*/ +#endif } else { @@ -1568,7 +1575,7 @@ namespace libtorrent #endif if (offset == i->second.offset) { -/* +#ifdef TORRENT_PARTIAL_HASH_LOG out << time_now_string() << " UPDATING [" " s: " << this << " p: " << piece_index @@ -1576,11 +1583,12 @@ namespace libtorrent << " size: " << size << " entries: " << m_piece_hasher.size() << " ]" << std::endl; -*/ +#endif i->second.offset += size; i->second.h.update(buf, size); } -/* else +#ifdef TORRENT_PARTIAL_HASH_LOG + else { out << time_now_string() << " SKIPPING (out of order) [" " s: " << this @@ -1590,8 +1598,10 @@ namespace libtorrent << " entries: " << m_piece_hasher.size() << " ]" << std::endl; } -*/ } -/* else +#endif + } +#ifdef TORRENT_PARTIAL_HASH_LOG + else { out << time_now_string() << " SKIPPING (no entry) [" " s: " << this @@ -1601,7 +1611,7 @@ namespace libtorrent << " entries: " << m_piece_hasher.size() << " ]" << std::endl; } -*/ +#endif } return ret; diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index 33827d4a9..cfeeffa86 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -1397,10 +1397,13 @@ namespace libtorrent // since this piece just passed, we might have // become uninterested in some peers where this // was the last piece we were interested in - for (peer_iterator i = m_connections.begin() - , end(m_connections.end()); i != end; ++i) + for (peer_iterator i = m_connections.begin(); + i != m_connections.end();) { peer_connection* p = *i; + // update_interest may disconnect the peer and + // invalidate the iterator + ++i; // if we're not interested already, no need to check if (!p->is_interesting()) continue; // if the peer doesn't have the piece we just got, it @@ -1835,6 +1838,8 @@ namespace libtorrent size_type size = m_torrent_file->files().at(i).size; if (size == 0) continue; position += size; + if (m_file_priority[i] == 0) continue; + // mark all pieces of the file with this file's priority // but only if the priority is higher than the pieces // already set (to avoid problems with overlapping pieces) @@ -1854,8 +1859,14 @@ namespace libtorrent // updates the interested flag in peers void torrent::update_peer_interest(bool was_finished) { - for (peer_iterator i = begin(); i != end(); ++i) - (*i)->update_interest(); + for (peer_iterator i = begin(); i != end();) + { + peer_connection* p = *i; + // update_interest may disconnect the peer and + // invalidate the iterator + ++i; + p->update_interest(); + } // the torrent just became finished if (is_finished() && !was_finished) diff --git a/libtorrent/src/udp_socket.cpp b/libtorrent/src/udp_socket.cpp index 78091116a..3a5c00892 100644 --- a/libtorrent/src/udp_socket.cpp +++ b/libtorrent/src/udp_socket.cpp @@ -30,6 +30,8 @@ void udp_socket::send(udp::endpoint const& ep, char const* p, int len, error_cod { if (ec == asio::error::operation_aborted) return; + mutex_t::scoped_lock l(m_mutex); + if (m_tunnel_packets) { // send udp packets through SOCKS5 server @@ -47,6 +49,8 @@ void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_ { if (e == asio::error::operation_aborted) return; + mutex_t::scoped_lock l(m_mutex); + if (!m_callback) return; if (e) @@ -55,9 +59,9 @@ void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_ try { #endif if (s == &m_ipv4_sock) - m_callback(e, m_v4_ep, 0, 0); + get_io_service().post(boost::bind(m_callback, e, m_v4_ep, (char*)0, 0)); else - m_callback(e, m_v6_ep, 0, 0); + get_io_service().post(boost::bind(m_callback, e, m_v6_ep, (char*)0, 0)); #ifndef BOOST_NO_EXCEPTIONS } catch(std::exception&) {} #endif @@ -90,7 +94,7 @@ void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_ if (m_tunnel_packets && m_v4_ep == m_proxy_addr) unwrap(e, m_v4_buf, bytes_transferred); else - m_callback(e, m_v4_ep, m_v4_buf, bytes_transferred); + get_io_service().post(boost::bind(m_callback, e, m_v4_ep, m_v4_buf, bytes_transferred)); #ifndef BOOST_NO_EXCEPTIONS } catch(std::exception&) {} @@ -107,7 +111,7 @@ void udp_socket::on_read(udp::socket* s, error_code const& e, std::size_t bytes_ if (m_tunnel_packets && m_v6_ep == m_proxy_addr) unwrap(e, m_v6_buf, bytes_transferred); else - m_callback(e, m_v6_ep, m_v6_buf, bytes_transferred); + get_io_service().post(boost::bind(m_callback, e, m_v6_ep, m_v6_buf, bytes_transferred)); #ifndef BOOST_NO_EXCEPTIONS } catch(std::exception&) {} @@ -173,11 +177,13 @@ void udp_socket::unwrap(error_code const& e, char const* buf, int size) return; } - m_callback(e, sender, p, size - (p - buf)); + get_io_service().post(boost::bind(m_callback, e, sender, p, size - (p - buf))); } void udp_socket::close() { + mutex_t::scoped_lock l(m_mutex); + error_code ec; m_ipv4_sock.close(ec); m_ipv6_sock.close(ec); @@ -192,6 +198,8 @@ void udp_socket::close() void udp_socket::bind(udp::endpoint const& ep, error_code& ec) { + mutex_t::scoped_lock l(m_mutex); + if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec); if (m_ipv6_sock.is_open()) m_ipv6_sock.close(ec); @@ -218,6 +226,8 @@ void udp_socket::bind(udp::endpoint const& ep, error_code& ec) void udp_socket::bind(int port) { + mutex_t::scoped_lock l(m_mutex); + error_code ec; if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec); @@ -243,6 +253,8 @@ void udp_socket::bind(int port) void udp_socket::set_proxy_settings(proxy_settings const& ps) { + mutex_t::scoped_lock l(m_mutex); + error_code ec; m_socks5_sock.close(ec); m_tunnel_packets = false; @@ -263,6 +275,9 @@ void udp_socket::set_proxy_settings(proxy_settings const& ps) void udp_socket::on_name_lookup(error_code const& e, tcp::resolver::iterator i) { if (e) return; + + mutex_t::scoped_lock l(m_mutex); + m_proxy_addr.address(i->endpoint().address()); m_proxy_addr.port(i->endpoint().port()); m_cc.enqueue(boost::bind(&udp_socket::on_connect, this, _1) @@ -271,6 +286,8 @@ void udp_socket::on_name_lookup(error_code const& e, tcp::resolver::iterator i) void udp_socket::on_timeout() { + mutex_t::scoped_lock l(m_mutex); + error_code ec; m_socks5_sock.close(ec); m_connection_ticket = -1; @@ -278,6 +295,8 @@ void udp_socket::on_timeout() void udp_socket::on_connect(int ticket) { + mutex_t::scoped_lock l(m_mutex); + m_connection_ticket = ticket; error_code ec; m_socks5_sock.open(m_proxy_addr.address().is_v4()?tcp::v4():tcp::v6(), ec); @@ -291,6 +310,8 @@ void udp_socket::on_connected(error_code const& e) m_connection_ticket = -1; if (e) return; + mutex_t::scoped_lock l(m_mutex); + using namespace libtorrent::detail; // send SOCKS5 authentication methods @@ -316,6 +337,8 @@ void udp_socket::handshake1(error_code const& e) { if (e) return; + mutex_t::scoped_lock l(m_mutex); + asio::async_read(m_socks5_sock, asio::buffer(m_tmp_buf, 2) , boost::bind(&udp_socket::handshake2, this, _1)); } @@ -326,6 +349,8 @@ void udp_socket::handshake2(error_code const& e) using namespace libtorrent::detail; + mutex_t::scoped_lock l(m_mutex); + char* p = &m_tmp_buf[0]; int version = read_uint8(p); int method = read_uint8(p); @@ -367,6 +392,8 @@ void udp_socket::handshake3(error_code const& e) { if (e) return; + mutex_t::scoped_lock l(m_mutex); + asio::async_read(m_socks5_sock, asio::buffer(m_tmp_buf, 2) , boost::bind(&udp_socket::handshake4, this, _1)); } @@ -375,6 +402,8 @@ void udp_socket::handshake4(error_code const& e) { if (e) return; + mutex_t::scoped_lock l(m_mutex); + using namespace libtorrent::detail; char* p = &m_tmp_buf[0]; @@ -391,6 +420,8 @@ void udp_socket::socks_forward_udp() { using namespace libtorrent::detail; + mutex_t::scoped_lock l(m_mutex); + // send SOCKS5 UDP command char* p = &m_tmp_buf[0]; write_uint8(5, p); // SOCKS VERSION 5 @@ -408,6 +439,8 @@ void udp_socket::connect1(error_code const& e) { if (e) return; + mutex_t::scoped_lock l(m_mutex); + asio::async_read(m_socks5_sock, asio::buffer(m_tmp_buf, 10) , boost::bind(&udp_socket::connect2, this, _1)); } @@ -415,7 +448,9 @@ void udp_socket::connect1(error_code const& e) void udp_socket::connect2(error_code const& e) { if (e) return; - + + mutex_t::scoped_lock l(m_mutex); + using namespace libtorrent::detail; char* p = &m_tmp_buf[0];