diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 4604ce616..116fcc0d6 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -166,7 +166,7 @@ namespace libtorrent #endif friend struct checker_impl; friend class invariant_access; - typedef std::map + typedef std::map , boost::intrusive_ptr > connection_map; typedef std::map > torrent_map; @@ -187,7 +187,7 @@ namespace libtorrent void open_listen_port(); void async_accept(); - void on_incoming_connection(boost::shared_ptr const& s + void on_incoming_connection(boost::shared_ptr const& s , boost::weak_ptr const& as, asio::error_code const& e); // must be locked to access the data @@ -205,7 +205,7 @@ namespace libtorrent void close_connection(boost::intrusive_ptr const& p); void connection_completed(boost::intrusive_ptr const& p); - void connection_failed(boost::shared_ptr const& s + void connection_failed(boost::shared_ptr const& s , tcp::endpoint const& a, char const* message); void set_settings(session_settings const& s); diff --git a/include/libtorrent/bt_peer_connection.hpp b/include/libtorrent/bt_peer_connection.hpp index eb214c341..223bf2650 100755 --- a/include/libtorrent/bt_peer_connection.hpp +++ b/include/libtorrent/bt_peer_connection.hpp @@ -90,7 +90,7 @@ namespace libtorrent bt_peer_connection( aux::session_impl& ses , boost::weak_ptr t - , boost::shared_ptr s + , boost::shared_ptr s , tcp::endpoint const& remote , policy::peer* peerinfo); @@ -98,7 +98,7 @@ namespace libtorrent // know which torrent the connection belongs to bt_peer_connection( aux::session_impl& ses - , boost::shared_ptr s + , boost::shared_ptr s , policy::peer* peerinfo); ~bt_peer_connection(); diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index e199ab503..b60c718c8 100755 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -72,6 +72,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/session.hpp" #include "libtorrent/bandwidth_manager.hpp" #include "libtorrent/policy.hpp" +#include "libtorrent/variant_stream.hpp" // TODO: each time a block is 'taken over' // from another peer. That peer must be given @@ -103,6 +104,8 @@ namespace libtorrent friend void intrusive_ptr_release(peer_connection const*); public: + typedef variant_stream socket_type; + enum channels { upload_channel, @@ -116,7 +119,7 @@ namespace libtorrent peer_connection( aux::session_impl& ses , boost::weak_ptr t - , boost::shared_ptr s + , boost::shared_ptr s , tcp::endpoint const& remote , tcp::endpoint const& proxy , policy::peer* peerinfo); @@ -125,7 +128,7 @@ namespace libtorrent // know which torrent the connection belongs to peer_connection( aux::session_impl& ses - , boost::shared_ptr s + , boost::shared_ptr s , policy::peer* peerinfo); virtual ~peer_connection(); @@ -216,7 +219,7 @@ namespace libtorrent // is called once every second by the main loop void second_tick(float tick_interval); - boost::shared_ptr get_socket() const { return m_socket; } + boost::shared_ptr get_socket() const { return m_socket; } tcp::endpoint const& remote() const { return m_remote; } tcp::endpoint const& proxy() const { return m_remote_proxy; } @@ -490,7 +493,7 @@ namespace libtorrent ptime m_last_receive; ptime m_last_sent; - boost::shared_ptr m_socket; + boost::shared_ptr m_socket; // this is the peer we're actually talking to // it may not necessarily be the peer we're // connected to, in case we use a proxy diff --git a/include/libtorrent/variant_stream.hpp b/include/libtorrent/variant_stream.hpp new file mode 100644 index 000000000..1049c5749 --- /dev/null +++ b/include/libtorrent/variant_stream.hpp @@ -0,0 +1,598 @@ +// Copyright Daniel Wallin and Arvid Norberg 2007. +// Use, modification and distribution is +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef VARIANT_STREAM_070211_HPP +# define VARIANT_STREAM_070211_HPP + +# include + +# include +# include +# include +# include +# include + +# include +# include +# include + +# include +# include + +#include + +# define NETWORK_VARIANT_STREAM_LIMIT 5 + +namespace libtorrent { + +namespace aux +{ + + struct delete_visitor + : boost::static_visitor<> + { + template + void operator()(T* p) const + { + delete p; + } + + void operator()(boost::blank) const + {} + }; + +// -------------- async_connect ----------- + + template + struct async_connect_visitor + : boost::static_visitor<> + { + async_connect_visitor(EndpointType const& endpoint, Handler const& handler) + : endpoint(endpoint) + , handler(handler) + {} + + template + void operator()(T* p) const + { + p->async_connect(endpoint, handler); + } + + void operator()(boost::blank) const + {} + + EndpointType const& endpoint; + Handler const& handler; + }; + +// -------------- bind ----------- + + template + struct bind_visitor + : boost::static_visitor<> + { + bind_visitor(EndpointType const& ep, Error_Handler const& error_handler) + : endpoint(ep) + , error_handler(error_handler) + {} + + template + void operator()(T* p) const + { + p->bind(endpoint, error_handler); + } + + void operator()(boost::blank) const + {} + + EndpointType const& endpoint; + Error_Handler const& error_handler; + }; + + template + struct bind_visitor + : boost::static_visitor<> + { + bind_visitor(EndpointType const& ep) + : endpoint(ep) + {} + + template + void operator()(T* p) const + { + p->bind(endpoint); + } + + void operator()(boost::blank) const + {} + + EndpointType const& endpoint; + }; + +// -------------- open ----------- + + template + struct open_visitor + : boost::static_visitor<> + { + open_visitor(Protocol const& p, Error_Handler const& error_handler) + : proto(p) + , error_handler(error_handler) + {} + + template + void operator()(T* p) const + { + p->open(proto, error_handler); + } + + void operator()(boost::blank) const + {} + + Protocol const& proto; + Error_Handler const& error_handler; + }; + + template + struct open_visitor + : boost::static_visitor<> + { + open_visitor(Protocol const& p) + : proto(p) + {} + + template + void operator()(T* p) const + { + p->open(proto); + } + + void operator()(boost::blank) const + {} + + Protocol const& proto; + }; + +// -------------- close ----------- + + template + struct close_visitor + : boost::static_visitor<> + { + close_visitor(Error_Handler const& error_handler) + : error_handler(error_handler) + {} + + template + void operator()(T* p) const + { + p->close(error_handler); + } + + void operator()(boost::blank) const + {} + + Error_Handler const& error_handler; + }; + + template <> + struct close_visitor + : boost::static_visitor<> + { + template + void operator()(T* p) const + { + p->close(); + } + + void operator()(boost::blank) const + {} + }; + +// -------------- remote_endpoint ----------- + + template + struct remote_endpoint_visitor + : boost::static_visitor + { + remote_endpoint_visitor(Error_Handler const& error_handler) + : error_handler(error_handler) + {} + + template + EndpointType operator()(T* p) const + { + return p->remote_endpoint(error_handler); + } + + EndpointType operator()(boost::blank) const + { + return EndpointType(); + } + + Error_Handler const& error_handler; + }; + + template + struct remote_endpoint_visitor + : boost::static_visitor + { + template + EndpointType operator()(T* p) const + { + return p->remote_endpoint(); + } + + EndpointType operator()(boost::blank) const + { + return EndpointType(); + } + }; + +// -------------- local_endpoint ----------- + + template + struct local_endpoint_visitor + : boost::static_visitor + { + local_endpoint_visitor(Error_Handler const& error_handler) + : error_handler(error_handler) + {} + + template + EndpointType operator()(T* p) const + { + return p->local_endpoint(error_handler); + } + + EndpointType operator()(boost::blank) const + { + return EndpointType(); + } + + Error_Handler const& error_handler; + }; + + template + struct local_endpoint_visitor + : boost::static_visitor + { + template + EndpointType operator()(T* p) const + { + return p->local_endpoint(); + } + + EndpointType operator()(boost::blank) const + { + return EndpointType(); + } + }; + +// -------------- async_read_some ----------- + + template + struct async_read_some_visitor + : boost::static_visitor<> + { + async_read_some_visitor(Mutable_Buffers const& buffers, Handler& handler) + : buffers(buffers) + , handler(handler) + {} + + template + void operator()(T* p) const + { + p->async_read_some(buffers, handler); + } + void operator()(boost::blank) const + {} + + Mutable_Buffers const& buffers; + Handler& handler; + }; + +// -------------- async_write_some ----------- + + template + struct async_write_some_visitor + : boost::static_visitor<> + { + async_write_some_visitor(Const_Buffers const& buffers, Handler& handler) + : buffers(buffers) + , handler(handler) + {} + + template + void operator()(T* p) const + { + p->async_write_some(buffers, handler); + } + + void operator()(boost::blank) const + {} + + Const_Buffers const& buffers; + Handler& handler; + }; + +// -------------- in_avail ----------- + + template + struct in_avail_visitor + : boost::static_visitor + { + in_avail_visitor(Error_Handler const& error_handler) + : error_handler(error_handler) + {} + + template + std::size_t operator()(T* p) const + { + return p->in_avail(error_handler); + } + + std::size_t operator()(boost::blank) const + { + return 0; + } + + Error_Handler const& error_handler; + }; + + template <> + struct in_avail_visitor + : boost::static_visitor + { + template + std::size_t operator()(T* p) const + { + return p->in_avail(); + } + + void operator()(boost::blank) const + {} + }; + +// -------------- io_service ----------- + + template + struct io_service_visitor + : boost::static_visitor + { + template + IOService& operator()(T* p) const + { + return p->io_service(); + } + + IOService& operator()(boost::blank) const + { + return *(IOService*)0; + } + }; + +// -------------- lowest_layer ----------- + + template + struct lowest_layer_visitor + : boost::static_visitor + { + template + LowestLayer& operator()(T* p) const + { + return p->lowest_layer(); + } + + LowestLayer& operator()(boost::blank) const + { + return *(LowestLayer*)0; + } + }; + +} // namespace aux + +template < + BOOST_PP_ENUM_BINARY_PARAMS( + NETWORK_VARIANT_STREAM_LIMIT, class S, = boost::mpl::void_ BOOST_PP_INTERCEPT + ) +> +class variant_stream : boost::noncopyable +{ +public: + typedef BOOST_PP_CAT(boost::mpl::vector, NETWORK_VARIANT_STREAM_LIMIT)< + BOOST_PP_ENUM_PARAMS(NETWORK_VARIANT_STREAM_LIMIT, S) + > types0; + + typedef typename boost::mpl::remove::type types; + + typedef typename boost::make_variant_over< + typename boost::mpl::push_back< + typename boost::mpl::transform< + types + , boost::add_pointer + >::type + , boost::blank + >::type + >::type variant_type; + + typedef typename S0::lowest_layer_type lowest_layer_type; + 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()) + {} + + template + void instantiate() + { + std::auto_ptr owned(new S(m_io_service)); + boost::apply_visitor(aux::delete_visitor(), m_variant); + m_variant = owned.get(); + owned.release(); + } + + template + S& get() + { + return *boost::get(m_variant); + } + + bool instantiated() const + { + return m_variant.which() != boost::mpl::size::value; + } + + ~variant_stream() + { + boost::apply_visitor(aux::delete_visitor(), m_variant); + } + + template + void async_read_some(Mutable_Buffers const& buffers, Handler handler) + { + assert(instantiated()); + boost::apply_visitor( + aux::async_read_some_visitor(buffers, handler) + , m_variant + ); + } + + template + void async_write_some(Const_Buffers const& buffers, Handler handler) + { + assert(instantiated()); + boost::apply_visitor( + aux::async_write_some_visitor(buffers, handler) + , m_variant + ); + } + + template + void async_connect(endpoint_type const& endpoint, Handler handler) + { + assert(instantiated()); + boost::apply_visitor( + aux::async_connect_visitor(endpoint, handler), m_variant + ); + } + + void bind(endpoint_type const& endpoint) + { + assert(instantiated()); + boost::apply_visitor(aux::bind_visitor(endpoint), m_variant); + } + + template + void bind(endpoint_type const& endpoint, Error_Handler error_handler) + { + assert(instantiated()); + boost::apply_visitor( + aux::bind_visitor(endpoint, error_handler), m_variant + ); + } + + void open(protocol_type const& p) + { + assert(instantiated()); + boost::apply_visitor(aux::open_visitor(p), m_variant); + } + + template + void open(protocol_type const& p, Error_Handler error_handler) + { + assert(instantiated()); + boost::apply_visitor( + aux::open_visitor(p, error_handler), m_variant + ); + } + + void close() + { + assert(instantiated()); + boost::apply_visitor(aux::close_visitor<>(), m_variant); + } + + template + void close(Error_Handler error_handler) + { + assert(instantiated()); + boost::apply_visitor( + aux::close_visitor(error_handler), m_variant + ); + } + + std::size_t in_avail() + { + assert(instantiated()); + return boost::apply_visitor(aux::in_avail_visitor<>(), m_variant); + } + + template + std::size_t in_avail(Error_Handler error_handler) + { + assert(instantiated()); + return boost::apply_visitor( + aux::in_avail_visitor(error_handler), m_variant + ); + } + + endpoint_type remote_endpoint() + { + assert(instantiated()); + return boost::apply_visitor(aux::remote_endpoint_visitor(), m_variant); + } + + template + endpoint_type remote_endpoint(Error_Handler error_handler) + { + assert(instantiated()); + return boost::apply_visitor( + aux::remote_endpoint_visitor(error_handler), m_variant + ); + } + + endpoint_type local_endpoint() + { + assert(instantiated()); + return boost::apply_visitor(aux::local_endpoint_visitor(), m_variant); + } + + template + endpoint_type local_endpoint(Error_Handler error_handler) + { + assert(instantiated()); + return boost::apply_visitor( + aux::local_endpoint_visitor(error_handler), m_variant + ); + } + + asio::io_service& io_service() + { + assert(instantiated()); + return boost::apply_visitor( + aux::io_service_visitor(), m_variant + ); + } + + lowest_layer_type& lowest_layer() + { + assert(instantiated()); + return boost::apply_visitor( + aux::lowest_layer_visitor(), m_variant + ); + } + +private: + asio::io_service& m_io_service; + variant_type m_variant; +}; + +} // namespace network + +#endif // VARIANT_STREAM_070211_HPP + diff --git a/include/libtorrent/web_peer_connection.hpp b/include/libtorrent/web_peer_connection.hpp index 950b593fa..bd1e85079 100755 --- a/include/libtorrent/web_peer_connection.hpp +++ b/include/libtorrent/web_peer_connection.hpp @@ -95,7 +95,7 @@ namespace libtorrent web_peer_connection( aux::session_impl& ses , boost::weak_ptr t - , boost::shared_ptr s + , boost::shared_ptr s , tcp::endpoint const& remote , tcp::endpoint const& proxy , std::string const& url diff --git a/src/bt_peer_connection.cpp b/src/bt_peer_connection.cpp index 9aa7b7986..b5deaad1f 100755 --- a/src/bt_peer_connection.cpp +++ b/src/bt_peer_connection.cpp @@ -78,7 +78,7 @@ namespace libtorrent bt_peer_connection::bt_peer_connection( session_impl& ses , boost::weak_ptr tor - , shared_ptr s + , shared_ptr s , tcp::endpoint const& remote , policy::peer* peerinfo) : peer_connection(ses, tor, s, remote @@ -119,7 +119,7 @@ namespace libtorrent bt_peer_connection::bt_peer_connection( session_impl& ses - , boost::shared_ptr s + , boost::shared_ptr s , policy::peer* peerinfo) : peer_connection(ses, s, peerinfo) , m_state(read_protocol_length) @@ -1073,16 +1073,6 @@ namespace libtorrent || !std::equal(recv_buffer.begin, recv_buffer.end , protocol_string)) { - const char cmd[] = "version"; - if (recv_buffer.end - recv_buffer.begin == 7 && std::equal( - recv_buffer.begin, recv_buffer.end, cmd)) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "sending libtorrent version\n"; -#endif - asio::write(*get_socket(), asio::buffer("libtorrent version " LIBTORRENT_VERSION "\n", 27)); - throw std::runtime_error("closing"); - } #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << "incorrect protocol name\n"; #endif diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index e13b46d47..2db89145e 100755 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -76,7 +76,7 @@ namespace libtorrent peer_connection::peer_connection( session_impl& ses , boost::weak_ptr tor - , shared_ptr s + , shared_ptr s , tcp::endpoint const& remote , tcp::endpoint const& proxy , policy::peer* peerinfo) @@ -146,7 +146,7 @@ namespace libtorrent peer_connection::peer_connection( session_impl& ses - , boost::shared_ptr s + , boost::shared_ptr s , policy::peer* peerinfo) : #ifndef NDEBUG @@ -1551,10 +1551,9 @@ namespace libtorrent } - void close_socket_ignore_error(boost::shared_ptr s) + void close_socket_ignore_error(boost::shared_ptr s) { - asio::error_code e; - s->close(e); + try { s->close(); } catch (std::exception& e) {} } void peer_connection::disconnect() diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 6c3e300c2..dcea29c6f 100755 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -729,13 +729,14 @@ namespace libtorrent { namespace detail void session_impl::async_accept() { - shared_ptr c(new stream_socket(m_io_service)); - m_listen_socket->async_accept(*c + shared_ptr c(new peer_connection::socket_type(m_io_service)); + c->instantiate(); + m_listen_socket->async_accept(c->get() , bind(&session_impl::on_incoming_connection, this, c , weak_ptr(m_listen_socket), _1)); } - void session_impl::on_incoming_connection(shared_ptr const& s + void session_impl::on_incoming_connection(shared_ptr const& s , weak_ptr const& listen_socket, asio::error_code const& e) try { if (listen_socket.expired()) @@ -796,7 +797,7 @@ namespace libtorrent { namespace detail #endif } - void session_impl::connection_failed(boost::shared_ptr const& s + void session_impl::connection_failed(boost::shared_ptr const& s , tcp::endpoint const& a, char const* message) #ifndef NDEBUG try diff --git a/src/torrent.cpp b/src/torrent.cpp index cbc5743b8..ac840f3ef 100755 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -1488,7 +1488,9 @@ namespace libtorrent else return; } - boost::shared_ptr s(new stream_socket(m_ses.m_io_service)); + boost::shared_ptr s( + new peer_connection::socket_type(m_ses.m_io_service)); + s->instantiate(); boost::intrusive_ptr c(new web_peer_connection( m_ses, shared_from_this(), s, a, proxy, url, 0)); @@ -1873,7 +1875,9 @@ namespace libtorrent if (m_connections.find(a) != m_connections.end()) throw protocol_error("already connected to peer"); - boost::shared_ptr s(new stream_socket(m_ses.m_io_service)); + boost::shared_ptr s( + new peer_connection::socket_type(m_ses.m_io_service)); + s->instantiate(); boost::intrusive_ptr c(new bt_peer_connection( m_ses, shared_from_this(), s, a, peerinfo)); diff --git a/src/web_peer_connection.cpp b/src/web_peer_connection.cpp index cc74703d3..b90c4e37c 100755 --- a/src/web_peer_connection.cpp +++ b/src/web_peer_connection.cpp @@ -59,7 +59,7 @@ namespace libtorrent web_peer_connection::web_peer_connection( session_impl& ses , boost::weak_ptr t - , boost::shared_ptr s + , boost::shared_ptr s , tcp::endpoint const& remote , tcp::endpoint const& proxy , std::string const& url