diff --git a/libtorrent/include/libtorrent/http_tracker_connection.hpp b/libtorrent/include/libtorrent/http_tracker_connection.hpp index 70be3054a..5b618c876 100755 --- a/libtorrent/include/libtorrent/http_tracker_connection.hpp +++ b/libtorrent/include/libtorrent/http_tracker_connection.hpp @@ -159,7 +159,7 @@ namespace libtorrent asio::strand& m_strand; tcp::resolver m_name_lookup; int m_port; - boost::shared_ptr m_socket; + socket_type m_socket; int m_recv_pos; std::vector m_buffer; std::string m_send_buffer; diff --git a/libtorrent/include/libtorrent/instantiate_connection.hpp b/libtorrent/include/libtorrent/instantiate_connection.hpp index 49cb1fe18..71282f993 100644 --- a/libtorrent/include/libtorrent/instantiate_connection.hpp +++ b/libtorrent/include/libtorrent/instantiate_connection.hpp @@ -41,8 +41,8 @@ namespace libtorrent { struct proxy_settings; - boost::shared_ptr instantiate_connection( - asio::io_service& ios, proxy_settings const& ps); + bool instantiate_connection(asio::io_service& ios + , proxy_settings const& ps, socket_type& s); } #endif diff --git a/libtorrent/include/libtorrent/proxy_base.hpp b/libtorrent/include/libtorrent/proxy_base.hpp index 021802dd0..f2a955958 100644 --- a/libtorrent/include/libtorrent/proxy_base.hpp +++ b/libtorrent/include/libtorrent/proxy_base.hpp @@ -104,10 +104,9 @@ public: m_sock.bind(endpoint); } - template - void bind(endpoint_type const& endpoint, Error_Handler const& error_handler) + void bind(endpoint_type const& endpoint, asio::error_code& ec) { - m_sock.bind(endpoint, error_handler); + m_sock.bind(endpoint, ec); } void open(protocol_type const& p) @@ -115,10 +114,9 @@ public: m_sock.open(p); } - template - void open(protocol_type const& p, Error_Handler const& error_handler) + void open(protocol_type const& p, asio::error_code& ec) { - m_sock.open(p, error_handler); + m_sock.open(p, ec); } void close() @@ -127,10 +125,9 @@ public: m_sock.close(); } - template - void close(Error_Handler const& error_handler) + void close(asio::error_code& ec) { - m_sock.close(error_handler); + m_sock.close(ec); } endpoint_type remote_endpoint() @@ -138,8 +135,7 @@ public: return m_remote_endpoint; } - template - endpoint_type remote_endpoint(Error_Handler const& error_handler) + endpoint_type remote_endpoint(asio::error_code& ec) { return m_remote_endpoint; } @@ -149,10 +145,9 @@ public: return m_sock.local_endpoint(); } - template - endpoint_type local_endpoint(Error_Handler const& error_handler) + endpoint_type local_endpoint(asio::error_code& ec) { - return m_sock.local_endpoint(error_handler); + return m_sock.local_endpoint(ec); } asio::io_service& io_service() @@ -168,7 +163,6 @@ public: protected: stream_socket m_sock; - // the socks5 proxy std::string m_hostname; int m_port; diff --git a/libtorrent/include/libtorrent/session_settings.hpp b/libtorrent/include/libtorrent/session_settings.hpp index a792e296a..8d57b27ec 100644 --- a/libtorrent/include/libtorrent/session_settings.hpp +++ b/libtorrent/include/libtorrent/session_settings.hpp @@ -87,7 +87,7 @@ namespace libtorrent , tracker_receive_timeout(20) , stop_tracker_timeout(5) , tracker_maximum_response_length(1024*1024) - , piece_timeout(120) + , piece_timeout(10) , request_queue_time(3.f) , max_allowed_in_request_queue(250) , max_out_request_queue(200) diff --git a/libtorrent/include/libtorrent/socks4_stream.hpp b/libtorrent/include/libtorrent/socks4_stream.hpp index 6110dbe4d..9530f9d57 100644 --- a/libtorrent/include/libtorrent/socks4_stream.hpp +++ b/libtorrent/include/libtorrent/socks4_stream.hpp @@ -89,3 +89,4 @@ private: } #endif + diff --git a/libtorrent/include/libtorrent/socks5_stream.hpp b/libtorrent/include/libtorrent/socks5_stream.hpp index 8bfc74c59..622557cd2 100644 --- a/libtorrent/include/libtorrent/socks5_stream.hpp +++ b/libtorrent/include/libtorrent/socks5_stream.hpp @@ -101,3 +101,4 @@ private: } #endif + diff --git a/libtorrent/include/libtorrent/torrent.hpp b/libtorrent/include/libtorrent/torrent.hpp index 60140f2c2..20779e6f5 100755 --- a/libtorrent/include/libtorrent/torrent.hpp +++ b/libtorrent/include/libtorrent/torrent.hpp @@ -424,6 +424,7 @@ namespace libtorrent } int block_size() const { TORRENT_ASSERT(m_block_size > 0); return m_block_size; } + peer_request to_req(piece_block const& p); // this will tell all peers that we just got his piece // and also let the piece picker know that we have this piece diff --git a/libtorrent/include/libtorrent/udp_tracker_connection.hpp b/libtorrent/include/libtorrent/udp_tracker_connection.hpp index c0e6853b9..e5eadc144 100755 --- a/libtorrent/include/libtorrent/udp_tracker_connection.hpp +++ b/libtorrent/include/libtorrent/udp_tracker_connection.hpp @@ -105,7 +105,7 @@ namespace libtorrent asio::strand& m_strand; udp::resolver m_name_lookup; - boost::shared_ptr m_socket; + datagram_socket m_socket; udp::endpoint m_target; udp::endpoint m_sender; diff --git a/libtorrent/include/libtorrent/variant_stream.hpp b/libtorrent/include/libtorrent/variant_stream.hpp index 4f45f5e01..ec012364f 100644 --- a/libtorrent/include/libtorrent/variant_stream.hpp +++ b/libtorrent/include/libtorrent/variant_stream.hpp @@ -501,15 +501,12 @@ public: typedef typename S0::endpoint_type endpoint_type; typedef typename S0::protocol_type protocol_type; - explicit variant_stream(asio::io_service& io_service) - : m_io_service(io_service) - , m_variant(boost::blank()) - {} + explicit variant_stream() : m_variant(boost::blank()) {} template - void instantiate() + void instantiate(asio::io_service& ios) { - std::auto_ptr owned(new S(m_io_service)); + std::auto_ptr owned(new S(ios)); boost::apply_visitor(aux::delete_visitor(), m_variant); m_variant = owned.get(); owned.release(); @@ -704,7 +701,6 @@ public: } private: - asio::io_service& m_io_service; variant_type m_variant; }; diff --git a/libtorrent/src/http_tracker_connection.cpp b/libtorrent/src/http_tracker_connection.cpp index de1783b58..ccca58226 100755 --- a/libtorrent/src/http_tracker_connection.cpp +++ b/libtorrent/src/http_tracker_connection.cpp @@ -496,7 +496,7 @@ namespace libtorrent void http_tracker_connection::on_timeout() { m_timed_out = true; - m_socket.reset(); + m_socket.close(); m_name_lookup.cancel(); if (m_connection_ticket > -1) m_cc.done(m_connection_ticket); m_connection_ticket = -1; @@ -550,18 +550,20 @@ namespace libtorrent } if (cb) cb->m_tracker_address = target_address; - m_socket = instantiate_connection(m_name_lookup.io_service(), m_proxy); + bool ret = instantiate_connection(m_strand.io_service(), m_proxy, m_socket); + + TORRENT_ASSERT(ret); if (m_proxy.type == proxy_settings::http || m_proxy.type == proxy_settings::http_pw) { // the tracker connection will talk immediately to // the proxy, without requiring CONNECT support - m_socket->get().set_no_connect(true); + m_socket.get().set_no_connect(true); } - m_socket->open(target_address.protocol()); - m_socket->bind(tcp::endpoint(bind_interface(), 0)); + m_socket.open(target_address.protocol()); + m_socket.bind(tcp::endpoint(bind_interface(), 0)); m_cc.enqueue(bind(&http_tracker_connection::connect, self(), _1, target_address) , bind(&http_tracker_connection::on_timeout, self()) , seconds(m_settings.tracker_receive_timeout)); @@ -574,7 +576,7 @@ namespace libtorrent void http_tracker_connection::connect(int ticket, tcp::endpoint target_address) { m_connection_ticket = ticket; - m_socket->async_connect(target_address, bind(&http_tracker_connection::connected, self(), _1)); + m_socket.async_connect(target_address, bind(&http_tracker_connection::connected, self(), _1)); } void http_tracker_connection::connected(asio::error_code const& error) try @@ -595,7 +597,7 @@ namespace libtorrent #endif restart_read_timeout(); - async_write(*m_socket, asio::buffer(m_send_buffer.c_str() + async_write(m_socket, asio::buffer(m_send_buffer.c_str() , m_send_buffer.size()), bind(&http_tracker_connection::sent , self(), _1)); } @@ -620,7 +622,7 @@ namespace libtorrent #endif restart_read_timeout(); TORRENT_ASSERT(m_buffer.size() - m_recv_pos > 0); - m_socket->async_read_some(asio::buffer(&m_buffer[m_recv_pos] + m_socket.async_read_some(asio::buffer(&m_buffer[m_recv_pos] , m_buffer.size() - m_recv_pos), bind(&http_tracker_connection::receive , self(), _1, _2)); } @@ -701,7 +703,7 @@ namespace libtorrent } TORRENT_ASSERT(m_buffer.size() - m_recv_pos > 0); - m_socket->async_read_some(asio::buffer(&m_buffer[m_recv_pos] + m_socket.async_read_some(asio::buffer(&m_buffer[m_recv_pos] , m_buffer.size() - m_recv_pos), bind(&http_tracker_connection::receive , self(), _1, _2)); } diff --git a/libtorrent/src/instantiate_connection.cpp b/libtorrent/src/instantiate_connection.cpp index 43b70f40d..f9c997fb1 100644 --- a/libtorrent/src/instantiate_connection.cpp +++ b/libtorrent/src/instantiate_connection.cpp @@ -42,42 +42,40 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { - boost::shared_ptr instantiate_connection( - asio::io_service& ios, proxy_settings const& ps) + bool instantiate_connection(asio::io_service& ios + , proxy_settings const& ps, socket_type& s) { - boost::shared_ptr s(new socket_type(ios)); - if (ps.type == proxy_settings::none) { - s->instantiate(); + s.instantiate(ios); } else if (ps.type == proxy_settings::http || ps.type == proxy_settings::http_pw) { - s->instantiate(); - s->get().set_proxy(ps.hostname, ps.port); + s.instantiate(ios); + s.get().set_proxy(ps.hostname, ps.port); if (ps.type == proxy_settings::socks5_pw) - s->get().set_username(ps.username, ps.password); + s.get().set_username(ps.username, ps.password); } else if (ps.type == proxy_settings::socks5 || ps.type == proxy_settings::socks5_pw) { - s->instantiate(); - s->get().set_proxy(ps.hostname, ps.port); + s.instantiate(ios); + s.get().set_proxy(ps.hostname, ps.port); if (ps.type == proxy_settings::socks5_pw) - s->get().set_username(ps.username, ps.password); + s.get().set_username(ps.username, ps.password); } else if (ps.type == proxy_settings::socks4) { - s->instantiate(); - s->get().set_proxy(ps.hostname, ps.port); - s->get().set_username(ps.username); + s.instantiate(ios); + s.get().set_proxy(ps.hostname, ps.port); + s.get().set_username(ps.username); } else { - throw std::runtime_error("unsupported proxy type"); + return false; } - return s; + return true; } } diff --git a/libtorrent/src/peer_connection.cpp b/libtorrent/src/peer_connection.cpp index 84d12a96d..2032b54c5 100755 --- a/libtorrent/src/peer_connection.cpp +++ b/libtorrent/src/peer_connection.cpp @@ -2209,18 +2209,19 @@ namespace libtorrent piece_picker& picker = t->picker(); while (!m_download_queue.empty()) { - picker.abort_download(m_download_queue.back()); + piece_block const& r = m_download_queue.back(); + picker.abort_download(r); + write_cancel(t->to_req(r)); m_download_queue.pop_back(); } while (!m_request_queue.empty()) { - picker.abort_download(m_request_queue.back()); + piece_block const& r = m_request_queue.back(); + picker.abort_download(r); + write_cancel(t->to_req(r)); m_request_queue.pop_back(); } - // TODO: If we have a limited number of upload - // slots, choke this peer - m_assume_fifo = true; request_a_block(*t, *this); @@ -2990,11 +2991,25 @@ namespace libtorrent // time, it is considered to have timed out time_duration d; d = now - m_last_receive; - if (d > seconds(m_timeout)) return true; + if (d > seconds(m_timeout)) + { +#ifdef TORRENT_VERBOSE_LOGGING + (*m_logger) << time_now_string() << " *** LAST ACTIVITY [ " + << total_seconds(d) << " seconds ago ] ***\n"; +#endif + return true; + } // if it takes more than 5 seconds to receive // handshake, disconnect - if (in_handshake() && d > seconds(5)) return true; + if (in_handshake() && d > seconds(5)) + { +#ifdef TORRENT_VERBOSE_LOGGING + (*m_logger) << time_now_string() << " *** NO HANDSHAKE [ " + << total_seconds(d) << " seconds ago ] ***\n"; +#endif + return true; + } // disconnect peers that we unchoked, but // they didn't send a request within 20 seconds. @@ -3005,7 +3020,14 @@ namespace libtorrent && !m_choked && m_peer_interested && t && t->is_finished() - && d > seconds(20)) return true; + && d > seconds(20)) + { +#ifdef TORRENT_VERBOSE_LOGGING + (*m_logger) << time_now_string() << " *** NO REQUEST [ t: " + << total_seconds(d) << " ] ***\n"; +#endif + return true; + } // TODO: as long as we have less than 95% of the // global (or local) connection limit, connections should @@ -3021,11 +3043,21 @@ namespace libtorrent time_duration time_limit = seconds( m_ses.settings().inactivity_timeout); + // don't bother disconnect peers we haven't been intersted + // in (and that hasn't been interested in us) for a while + // unless we have used up all our connection slots if (!m_interesting && !m_peer_interested && d1 > time_limit - && d2 > time_limit) + && d2 > time_limit + && (m_ses.num_connections() >= m_ses.max_connections() + || (t && t->num_peers() >= t->max_connections()))) { +#ifdef TORRENT_VERBOSE_LOGGING + (*m_logger) << time_now_string() << " *** MUTUAL NO INTEREST [ " + "t1: " << total_seconds(d1) << " | " + "t2: " << total_seconds(d2) << " ] ***\n"; +#endif return true; } @@ -3068,10 +3100,9 @@ namespace libtorrent if (m_writing) return; #ifdef TORRENT_VERBOSE_LOGGING - using namespace boost::posix_time; (*m_logger) << time_now_string() << " ==> KEEPALIVE\n"; #endif - + m_last_sent = time_now(); write_keepalive(); } diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp index a602c6fa4..299ba96a7 100755 --- a/libtorrent/src/session_impl.cpp +++ b/libtorrent/src/session_impl.cpp @@ -902,8 +902,8 @@ namespace detail void session_impl::async_accept(boost::shared_ptr const& listener) { - shared_ptr c(new socket_type(m_io_service)); - c->instantiate(); + shared_ptr c(new socket_type); + c->instantiate(m_io_service); listener->async_accept(c->get() , bind(&session_impl::on_incoming_connection, this, c , boost::weak_ptr(listener), _1)); diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index 088789d79..d14b3075d 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -326,6 +326,21 @@ namespace libtorrent disconnect_all(); } + peer_request torrent::to_req(piece_block const& p) + { + int block_offset = p.block_index * m_block_size; + int block_size = (std::min)((int)torrent_file().piece_size( + p.piece_index) - block_offset, m_block_size); + TORRENT_ASSERT(block_size > 0); + TORRENT_ASSERT(block_size <= m_block_size); + + peer_request r; + r.piece = p.piece_index; + r.start = block_offset; + r.length = block_size; + return r; + } + std::string torrent::name() const { if (valid_metadata()) return m_torrent_file->name(); @@ -1656,8 +1671,11 @@ namespace libtorrent else return; } - boost::shared_ptr s - = instantiate_connection(m_ses.m_io_service, m_ses.web_seed_proxy()); + boost::shared_ptr s(new socket_type); + + bool ret = instantiate_connection(m_ses.m_io_service, m_ses.web_seed_proxy(), *s); + TORRENT_ASSERT(ret); + if (m_ses.web_seed_proxy().type == proxy_settings::http || m_ses.web_seed_proxy().type == proxy_settings::http_pw) { @@ -1869,8 +1887,11 @@ namespace libtorrent tcp::endpoint const& a(peerinfo->ip); TORRENT_ASSERT((m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked) == 0); - boost::shared_ptr s - = instantiate_connection(m_ses.m_io_service, m_ses.peer_proxy()); + boost::shared_ptr s(new socket_type); + + bool ret = instantiate_connection(m_ses.m_io_service, m_ses.peer_proxy(), *s); + TORRENT_ASSERT(ret); + boost::intrusive_ptr c(new bt_peer_connection( m_ses, shared_from_this(), s, a, peerinfo)); diff --git a/libtorrent/src/udp_tracker_connection.cpp b/libtorrent/src/udp_tracker_connection.cpp index 1ba50b3c6..dd2ff10a1 100755 --- a/libtorrent/src/udp_tracker_connection.cpp +++ b/libtorrent/src/udp_tracker_connection.cpp @@ -86,6 +86,7 @@ namespace libtorrent , m_man(man) , m_strand(str) , m_name_lookup(m_strand.io_service()) + , m_socket(m_strand.io_service()) , m_transaction_id(0) , m_connection_id(0) , m_settings(stn) @@ -103,7 +104,7 @@ namespace libtorrent , udp::resolver::iterator i) try { if (error == asio::error::operation_aborted) return; - if (!m_socket) return; // the operation was aborted + if (!m_socket.is_open()) return; // the operation was aborted if (error || i == udp::resolver::iterator()) { fail(-1, error.message().c_str()); @@ -143,10 +144,9 @@ namespace libtorrent if (cb) cb->m_tracker_address = tcp::endpoint(target_address.address(), target_address.port()); m_target = target_address; - m_socket.reset(new datagram_socket(m_name_lookup.io_service())); - m_socket->open(target_address.protocol()); - m_socket->bind(udp::endpoint(bind_interface(), 0)); - m_socket->connect(target_address); + m_socket.open(target_address.protocol()); + m_socket.bind(udp::endpoint(bind_interface(), 0)); + m_socket.connect(target_address); send_udp_connect(); } catch (std::exception& e) @@ -156,7 +156,7 @@ namespace libtorrent void udp_tracker_connection::on_timeout() { - m_socket.reset(); + m_socket.close(); m_name_lookup.cancel(); fail_timeout(); } @@ -171,7 +171,7 @@ namespace libtorrent + lexical_cast(tracker_req().info_hash) + "]"); } #endif - if (!m_socket) return; // the operation was aborted + if (!m_socket.is_open()) return; // the operation was aborted char send_buf[16]; char* ptr = send_buf; @@ -187,10 +187,10 @@ namespace libtorrent // transaction_id detail::write_int32(m_transaction_id, ptr); - m_socket->send(asio::buffer((void*)send_buf, 16), 0); + m_socket.send(asio::buffer((void*)send_buf, 16), 0); ++m_attempts; m_buffer.resize(udp_buffer_size); - m_socket->async_receive_from(asio::buffer(m_buffer), m_sender + m_socket.async_receive_from(asio::buffer(m_buffer), m_sender , boost::bind(&udp_tracker_connection::connect_response, self(), _1, _2)); } @@ -198,7 +198,7 @@ namespace libtorrent , std::size_t bytes_transferred) try { if (error == asio::error::operation_aborted) return; - if (!m_socket) return; // the operation was aborted + if (!m_socket.is_open()) return; // the operation was aborted if (error) { fail(-1, error.message().c_str()); @@ -208,7 +208,7 @@ namespace libtorrent if (m_target != m_sender) { // this packet was not received from the tracker - m_socket->async_receive_from(asio::buffer(m_buffer), m_sender + m_socket.async_receive_from(asio::buffer(m_buffer), m_sender , boost::bind(&udp_tracker_connection::connect_response, self(), _1, _2)); return; } @@ -284,7 +284,7 @@ namespace libtorrent if (m_transaction_id == 0) m_transaction_id = rand() ^ (rand() << 16); - if (!m_socket) return; // the operation was aborted + if (!m_socket.is_open()) return; // the operation was aborted std::vector buf; std::back_insert_iterator > out(buf); @@ -332,10 +332,10 @@ namespace libtorrent } #endif - m_socket->send(asio::buffer(buf), 0); + m_socket.send(asio::buffer(buf), 0); ++m_attempts; - m_socket->async_receive_from(asio::buffer(m_buffer), m_sender + m_socket.async_receive_from(asio::buffer(m_buffer), m_sender , bind(&udp_tracker_connection::announce_response, self(), _1, _2)); } @@ -344,7 +344,7 @@ namespace libtorrent if (m_transaction_id == 0) m_transaction_id = rand() ^ (rand() << 16); - if (!m_socket) return; // the operation was aborted + if (!m_socket.is_open()) return; // the operation was aborted std::vector buf; std::back_insert_iterator > out(buf); @@ -358,10 +358,10 @@ namespace libtorrent // info_hash std::copy(tracker_req().info_hash.begin(), tracker_req().info_hash.end(), out); - m_socket->send(asio::buffer(&buf[0], buf.size()), 0); + m_socket.send(asio::buffer(&buf[0], buf.size()), 0); ++m_attempts; - m_socket->async_receive_from(asio::buffer(m_buffer), m_sender + m_socket.async_receive_from(asio::buffer(m_buffer), m_sender , bind(&udp_tracker_connection::scrape_response, self(), _1, _2)); } @@ -369,7 +369,7 @@ namespace libtorrent , std::size_t bytes_transferred) try { if (error == asio::error::operation_aborted) return; - if (!m_socket) return; // the operation was aborted + if (!m_socket.is_open()) return; // the operation was aborted if (error) { fail(-1, error.message().c_str()); @@ -379,7 +379,7 @@ namespace libtorrent if (m_target != m_sender) { // this packet was not received from the tracker - m_socket->async_receive_from(asio::buffer(m_buffer), m_sender + m_socket.async_receive_from(asio::buffer(m_buffer), m_sender , bind(&udp_tracker_connection::connect_response, self(), _1, _2)); return; } @@ -479,7 +479,7 @@ namespace libtorrent , std::size_t bytes_transferred) try { if (error == asio::error::operation_aborted) return; - if (!m_socket) return; // the operation was aborted + if (!m_socket.is_open()) return; // the operation was aborted if (error) { fail(-1, error.message().c_str()); @@ -489,7 +489,7 @@ namespace libtorrent if (m_target != m_sender) { // this packet was not received from the tracker - m_socket->async_receive_from(asio::buffer(m_buffer), m_sender + m_socket.async_receive_from(asio::buffer(m_buffer), m_sender , bind(&udp_tracker_connection::connect_response, self(), _1, _2)); return; }