diff --git a/libtorrent/include/libtorrent/aux_/session_impl.hpp b/libtorrent/include/libtorrent/aux_/session_impl.hpp index 0389bf3dc..9300a1ce3 100644 --- a/libtorrent/include/libtorrent/aux_/session_impl.hpp +++ b/libtorrent/include/libtorrent/aux_/session_impl.hpp @@ -185,7 +185,7 @@ namespace libtorrent ~session_impl(); #ifndef TORRENT_DISABLE_EXTENSIONS - void add_extension(boost::function(torrent*)> ext); + void add_extension(boost::function(torrent*, void*)> ext); #endif void operator()(); @@ -246,7 +246,8 @@ namespace libtorrent , entry const& resume_data , bool compact_mode , storage_constructor_type sc - , bool paused); + , bool paused + , void* userdata); torrent_handle add_torrent( char const* tracker_url @@ -256,7 +257,8 @@ namespace libtorrent , entry const& resume_data , bool compact_mode , storage_constructor_type sc - , bool paused); + , bool paused + , void* userdata); void remove_torrent(torrent_handle const& h); @@ -519,7 +521,7 @@ namespace libtorrent #ifndef TORRENT_DISABLE_EXTENSIONS typedef std::list(torrent*)> > extension_list_t; + torrent_plugin>(torrent*, void*)> > extension_list_t; extension_list_t m_extensions; #endif diff --git a/libtorrent/include/libtorrent/broadcast_socket.hpp b/libtorrent/include/libtorrent/broadcast_socket.hpp index bdfe30b6e..b7285ee9c 100644 --- a/libtorrent/include/libtorrent/broadcast_socket.hpp +++ b/libtorrent/include/libtorrent/broadcast_socket.hpp @@ -52,6 +52,7 @@ namespace libtorrent public: broadcast_socket(asio::io_service& ios, udp::endpoint const& multicast_endpoint , receive_handler_t const& handler); + ~broadcast_socket() { close(); } void send(char const* buffer, int size, asio::error_code& ec); void close(); diff --git a/libtorrent/include/libtorrent/disk_io_thread.hpp b/libtorrent/include/libtorrent/disk_io_thread.hpp index 16ee0bca4..e9103b9e4 100644 --- a/libtorrent/include/libtorrent/disk_io_thread.hpp +++ b/libtorrent/include/libtorrent/disk_io_thread.hpp @@ -50,6 +50,7 @@ namespace libtorrent , buffer_size(0) , piece(0) , offset(0) + , priority(0) {} enum action_t @@ -72,6 +73,12 @@ namespace libtorrent // to the error message std::string str; + // priority decides whether or not this + // job will skip entries in the queue or + // not. It always skips in front of entries + // with lower priority + int priority; + // this is called when operation completes boost::function callback; }; diff --git a/libtorrent/include/libtorrent/extensions.hpp b/libtorrent/include/libtorrent/extensions.hpp index 44fff9c36..fd48588e1 100644 --- a/libtorrent/include/libtorrent/extensions.hpp +++ b/libtorrent/include/libtorrent/extensions.hpp @@ -149,6 +149,12 @@ namespace libtorrent virtual bool on_cancel(peer_request const& req) { return false; } + virtual bool on_reject(peer_request const& req) + { return false; } + + virtual bool on_suggest(int index) + { return false; } + // called when an extended message is received. If returning true, // the message is not processed by any other plugin and if false // is returned the next plugin in the chain will receive it to diff --git a/libtorrent/include/libtorrent/extensions/metadata_transfer.hpp b/libtorrent/include/libtorrent/extensions/metadata_transfer.hpp index 210642161..c42136d70 100644 --- a/libtorrent/include/libtorrent/extensions/metadata_transfer.hpp +++ b/libtorrent/include/libtorrent/extensions/metadata_transfer.hpp @@ -48,7 +48,7 @@ namespace libtorrent { struct torrent_plugin; class torrent; - TORRENT_EXPORT boost::shared_ptr create_metadata_plugin(torrent*); + TORRENT_EXPORT boost::shared_ptr create_metadata_plugin(torrent*, void*); } #endif // TORRENT_METADATA_TRANSFER_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/extensions/ut_pex.hpp b/libtorrent/include/libtorrent/extensions/ut_pex.hpp index efd9ab4f6..ebf6aa834 100644 --- a/libtorrent/include/libtorrent/extensions/ut_pex.hpp +++ b/libtorrent/include/libtorrent/extensions/ut_pex.hpp @@ -48,7 +48,7 @@ namespace libtorrent { struct torrent_plugin; class torrent; - TORRENT_EXPORT boost::shared_ptr create_ut_pex_plugin(torrent*); + TORRENT_EXPORT boost::shared_ptr create_ut_pex_plugin(torrent*, void*); } #endif // TORRENT_UT_PEX_EXTENSION_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/peer_info.hpp b/libtorrent/include/libtorrent/peer_info.hpp index 046df2a6b..b07acffd4 100755 --- a/libtorrent/include/libtorrent/peer_info.hpp +++ b/libtorrent/include/libtorrent/peer_info.hpp @@ -72,7 +72,8 @@ namespace libtorrent dht = 0x2, pex = 0x4, lsd = 0x8, - resume_data = 0x10 + resume_data = 0x10, + incoming = 0x20 }; int source; diff --git a/libtorrent/include/libtorrent/piece_picker.hpp b/libtorrent/include/libtorrent/piece_picker.hpp index 94f274a27..64f6203d5 100755 --- a/libtorrent/include/libtorrent/piece_picker.hpp +++ b/libtorrent/include/libtorrent/piece_picker.hpp @@ -233,7 +233,7 @@ namespace libtorrent bool is_finished(piece_block block) const; // marks this piece-block as queued for downloading - void mark_as_downloading(piece_block block, void* peer + bool mark_as_downloading(piece_block block, void* peer , piece_state_t s); void mark_as_writing(piece_block block, void* peer); void mark_as_finished(piece_block block, void* peer); diff --git a/libtorrent/include/libtorrent/session.hpp b/libtorrent/include/libtorrent/session.hpp index 2ce19349e..3a9eb563b 100755 --- a/libtorrent/include/libtorrent/session.hpp +++ b/libtorrent/include/libtorrent/session.hpp @@ -150,7 +150,8 @@ namespace libtorrent , entry const& resume_data = entry() , bool compact_mode = true , bool paused = false - , storage_constructor_type sc = default_storage_constructor); + , storage_constructor_type sc = default_storage_constructor + , void* userdata = 0); torrent_handle add_torrent( char const* tracker_url @@ -160,7 +161,8 @@ namespace libtorrent , entry const& resume_data = entry() , bool compact_mode = true , bool paused = false - , storage_constructor_type sc = default_storage_constructor); + , storage_constructor_type sc = default_storage_constructor + , void* userdata = 0); session_proxy abort() { return session_proxy(m_impl); } @@ -181,7 +183,7 @@ namespace libtorrent #endif #ifndef TORRENT_DISABLE_EXTENSIONS - void add_extension(boost::function(torrent*)> ext); + void add_extension(boost::function(torrent*, void*)> ext); #endif void set_ip_filter(ip_filter const& f); diff --git a/libtorrent/include/libtorrent/storage.hpp b/libtorrent/include/libtorrent/storage.hpp index e52196c76..505be8b6c 100755 --- a/libtorrent/include/libtorrent/storage.hpp +++ b/libtorrent/include/libtorrent/storage.hpp @@ -202,7 +202,8 @@ namespace libtorrent void async_read( peer_request const& r , boost::function const& handler - , char* buffer = 0); + , char* buffer = 0 + , int priority = 0); void async_write( peer_request const& r diff --git a/libtorrent/src/broadcast_socket.cpp b/libtorrent/src/broadcast_socket.cpp index a937fc11b..85bd829dc 100644 --- a/libtorrent/src/broadcast_socket.cpp +++ b/libtorrent/src/broadcast_socket.cpp @@ -60,8 +60,6 @@ namespace libtorrent { // ignore the loopback if (i->endpoint().address() == address_v4((127 << 24) + 1)) continue; - // ignore addresses that are not on a local network - if (!is_local(i->endpoint().address())) continue; // ignore non-IPv4 addresses if (i->endpoint().address().is_v4()) break; } @@ -96,17 +94,24 @@ namespace libtorrent if (ec) continue; s->set_option(datagram_socket::reuse_address(true), ec); if (ec) continue; - s->bind(udp::endpoint(*i, 0), ec); + s->bind(udp::endpoint(address_v4::any(), multicast_endpoint.port()), ec); if (ec) continue; s->set_option(join_group(multicast_endpoint.address()), ec); if (ec) continue; s->set_option(outbound_interface(i->to_v4()), ec); if (ec) continue; - s->set_option(hops(255)); + s->set_option(hops(255), ec); + if (ec) continue; + s->set_option(enable_loopback(true), ec); + if (ec) continue; m_sockets.push_back(socket_entry(s)); socket_entry& se = m_sockets.back(); s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer)) , se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2)); +#ifndef NDEBUG +// std::cerr << "broadcast socket [ if: " << i->to_v4().to_string() +// << " group: " << multicast_endpoint.address() << " ]" << std::endl; +#endif } } @@ -117,7 +122,9 @@ namespace libtorrent { asio::error_code e; i->socket->send_to(asio::buffer(buffer, size), m_multicast_endpoint, 0, e); +#ifndef NDEBUG // std::cerr << " sending on " << i->socket->local_endpoint().address().to_string() << std::endl; +#endif if (e) ec = e; } } diff --git a/libtorrent/src/bt_peer_connection.cpp b/libtorrent/src/bt_peer_connection.cpp index 11a39675f..f7f137437 100755 --- a/libtorrent/src/bt_peer_connection.cpp +++ b/libtorrent/src/bt_peer_connection.cpp @@ -1221,7 +1221,7 @@ namespace libtorrent { tcp::endpoint adr(remote().address() , (unsigned short)listen_port->integer()); - t->get_policy().peer_from_tracker(adr, pid(), 0, 0); + t->get_policy().peer_from_tracker(adr, pid(), peer_info::incoming, 0); } } // there should be a version too diff --git a/libtorrent/src/disk_io_thread.cpp b/libtorrent/src/disk_io_thread.cpp index e07a884cf..9096cff0e 100644 --- a/libtorrent/src/disk_io_thread.cpp +++ b/libtorrent/src/disk_io_thread.cpp @@ -89,8 +89,15 @@ namespace libtorrent namespace { + // The semantic of this operator is: + // shouls lhs come before rhs in the job queue bool operator<(disk_io_job const& lhs, disk_io_job const& rhs) { + // NOTE: comparison inverted to make higher priority + // skip _in_front_of_ lower priority + if (lhs.priority > rhs.priority) return true; + if (lhs.priority < rhs.priority) return false; + if (lhs.storage.get() < rhs.storage.get()) return true; if (lhs.storage.get() > rhs.storage.get()) return false; if (lhs.piece < rhs.piece) return true; diff --git a/libtorrent/src/file.cpp b/libtorrent/src/file.cpp index 3d568d1f7..72876d528 100755 --- a/libtorrent/src/file.cpp +++ b/libtorrent/src/file.cpp @@ -247,19 +247,16 @@ namespace libtorrent void set_size(size_type s) { - size_type pos = tell(); - // Only set size if current file size not equals s. - // 2 as "m" argument is to be sure seek() sets SEEK_END on - // all compilers. - if(s != seek(0, 2)) +#ifdef _WIN32 +#error file.cpp is for posix systems only. use file_win.cpp on windows +#else + if (ftruncate(m_fd, s) < 0) { - seek(s - 1); - char dummy = 0; - read(&dummy, 1); - seek(s - 1); - write(&dummy, 1); + std::stringstream msg; + msg << "ftruncate failed: '" << strerror(errno); + throw file_error(msg.str()); } - seek(pos); +#endif } size_type seek(size_type offset, int m = 1) diff --git a/libtorrent/src/metadata_transfer.cpp b/libtorrent/src/metadata_transfer.cpp index a19dd3d3f..0623b156f 100644 --- a/libtorrent/src/metadata_transfer.cpp +++ b/libtorrent/src/metadata_transfer.cpp @@ -556,7 +556,7 @@ namespace libtorrent { namespace namespace libtorrent { - boost::shared_ptr create_metadata_plugin(torrent* t) + boost::shared_ptr create_metadata_plugin(torrent* t, void*) { return boost::shared_ptr(new metadata_plugin(*t)); } diff --git a/libtorrent/src/peer_connection.cpp b/libtorrent/src/peer_connection.cpp index ad2102f0d..7832b4444 100755 --- a/libtorrent/src/peer_connection.cpp +++ b/libtorrent/src/peer_connection.cpp @@ -687,6 +687,14 @@ namespace libtorrent boost::shared_ptr t = m_torrent.lock(); assert(t); +#ifndef TORRENT_DISABLE_EXTENSIONS + for (extension_list_t::iterator i = m_extensions.begin() + , end(m_extensions.end()); i != end; ++i) + { + if ((*i)->on_reject(r)) return; + } +#endif + std::deque::iterator i = std::find_if( m_download_queue.begin(), m_download_queue.end() , bind(match_request, boost::cref(r), _1, t->block_size())); @@ -743,7 +751,7 @@ namespace libtorrent void peer_connection::incoming_suggest(int index) { INVARIANT_CHECK; - + #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << time_now_string() << " <== SUGGEST_PIECE [ piece: " << index << " ]\n"; @@ -751,6 +759,14 @@ namespace libtorrent boost::shared_ptr t = m_torrent.lock(); if (!t) return; +#ifndef TORRENT_DISABLE_EXTENSIONS + for (extension_list_t::iterator i = m_extensions.begin() + , end(m_extensions.end()); i != end; ++i) + { + if ((*i)->on_suggest(index)) return; + } +#endif + if (t->have_piece(index)) return; if (m_suggested_pieces.size() > 9) @@ -1647,7 +1663,9 @@ namespace libtorrent state = piece_picker::slow; } - t->picker().mark_as_downloading(block, peer_info_struct(), state); + if (!t->picker().mark_as_downloading(block, peer_info_struct(), state)) + return; + if (t->alerts().should_post(alert::info)) { t->alerts().post_alert(block_downloading_alert(t->get_handle(), diff --git a/libtorrent/src/piece_picker.cpp b/libtorrent/src/piece_picker.cpp index 8fa623fa3..d509fdefd 100755 --- a/libtorrent/src/piece_picker.cpp +++ b/libtorrent/src/piece_picker.cpp @@ -1229,6 +1229,7 @@ namespace libtorrent bool piece_picker::can_pick(int piece, std::vector const& bitmask) const { + assert(piece >= 0 && piece < int(m_piece_map.size())); return bitmask[piece] && !m_piece_map[piece].have() && !m_piece_map[piece].downloading @@ -1554,7 +1555,7 @@ namespace libtorrent } - void piece_picker::mark_as_downloading(piece_block block + bool piece_picker::mark_as_downloading(piece_block block , void* peer, piece_state_t state) { TORRENT_PIECE_PICKER_INVARIANT_CHECK; @@ -1589,6 +1590,9 @@ namespace libtorrent = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index)); assert(i != m_downloads.end()); block_info& info = i->info[block.block_index]; + if (info.state == block_info::state_writing + || info.state == block_info::state_finished) + return false; assert(info.state == block_info::state_none || (info.state == block_info::state_requested && (info.num_peers > 0))); @@ -1601,6 +1605,7 @@ namespace libtorrent ++info.num_peers; if (i->state == none) i->state = state; } + return true; } int piece_picker::num_peers(piece_block block) const diff --git a/libtorrent/src/session.cpp b/libtorrent/src/session.cpp index 1d7a070c2..6298b3c2c 100755 --- a/libtorrent/src/session.cpp +++ b/libtorrent/src/session.cpp @@ -132,7 +132,7 @@ namespace libtorrent m_impl->abort(); } - void session::add_extension(boost::function(torrent*)> ext) + void session::add_extension(boost::function(torrent*, void*)> ext) { m_impl->add_extension(ext); } @@ -185,7 +185,7 @@ namespace libtorrent assert(!ti.m_half_metadata); boost::intrusive_ptr tip(new torrent_info(ti)); return m_impl->add_torrent(tip, save_path, resume_data - , compact_mode, sc, paused); + , compact_mode, sc, paused, 0); } torrent_handle session::add_torrent( @@ -194,11 +194,12 @@ namespace libtorrent , entry const& resume_data , bool compact_mode , bool paused - , storage_constructor_type sc) + , storage_constructor_type sc + , void* userdata) { assert(!ti->m_half_metadata); return m_impl->add_torrent(ti, save_path, resume_data - , compact_mode, sc, paused); + , compact_mode, sc, paused, userdata); } torrent_handle session::add_torrent( @@ -209,10 +210,11 @@ namespace libtorrent , entry const& e , bool compact_mode , bool paused - , storage_constructor_type sc) + , storage_constructor_type sc + , void* userdata) { return m_impl->add_torrent(tracker_url, info_hash, name, save_path, e - , compact_mode, sc, paused); + , compact_mode, sc, paused, userdata); } void session::remove_torrent(const torrent_handle& h) diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp index 0aeb84bbe..6e1129b99 100755 --- a/libtorrent/src/session_impl.cpp +++ b/libtorrent/src/session_impl.cpp @@ -593,7 +593,7 @@ namespace detail #ifndef TORRENT_DISABLE_EXTENSIONS void session_impl::add_extension( - boost::function(torrent*)> ext) + boost::function(torrent*, void*)> ext) { m_extensions.push_back(ext); } @@ -1474,7 +1474,8 @@ namespace detail , entry const& resume_data , bool compact_mode , storage_constructor_type sc - , bool paused) + , bool paused + , void* userdata) { // if you get this assert, you haven't managed to // open a listen port. call listen_on() first. @@ -1514,7 +1515,7 @@ namespace detail for (extension_list_t::iterator i = m_extensions.begin() , end(m_extensions.end()); i != end; ++i) { - boost::shared_ptr tp((*i)(torrent_ptr.get())); + boost::shared_ptr tp((*i)(torrent_ptr.get(), userdata)); if (tp) torrent_ptr->add_extension(tp); } #endif @@ -1554,7 +1555,8 @@ namespace detail , entry const& , bool compact_mode , storage_constructor_type sc - , bool paused) + , bool paused + , void* userdata) { // TODO: support resume data in this case @@ -1593,7 +1595,7 @@ namespace detail for (extension_list_t::iterator i = m_extensions.begin() , end(m_extensions.end()); i != end; ++i) { - boost::shared_ptr tp((*i)(torrent_ptr.get())); + boost::shared_ptr tp((*i)(torrent_ptr.get(), userdata)); if (tp) torrent_ptr->add_extension(tp); } #endif diff --git a/libtorrent/src/storage.cpp b/libtorrent/src/storage.cpp index e1ddd20ae..7124fab96 100755 --- a/libtorrent/src/storage.cpp +++ b/libtorrent/src/storage.cpp @@ -1084,7 +1084,8 @@ namespace libtorrent void piece_manager::async_read( peer_request const& r , boost::function const& handler - , char* buffer) + , char* buffer + , int priority) { disk_io_job j; j.storage = this; @@ -1093,6 +1094,7 @@ namespace libtorrent j.offset = r.start; j.buffer_size = r.length; j.buffer = buffer; + j.priority = priority; // if a buffer is not specified, only one block can be read // since that is the size of the pool allocator's buffers assert(r.length <= 16 * 1024 || buffer != 0); diff --git a/libtorrent/src/ut_pex.cpp b/libtorrent/src/ut_pex.cpp index 18cbf6c2f..15913573e 100644 --- a/libtorrent/src/ut_pex.cpp +++ b/libtorrent/src/ut_pex.cpp @@ -347,7 +347,7 @@ namespace libtorrent { namespace namespace libtorrent { - boost::shared_ptr create_ut_pex_plugin(torrent* t) + boost::shared_ptr create_ut_pex_plugin(torrent* t, void*) { if (t->torrent_file().priv()) {