diff --git a/docs/manual.html b/docs/manual.html
index c9ddc1f79..a98eb675a 100644
--- a/docs/manual.html
+++ b/docs/manual.html
@@ -2612,6 +2612,7 @@ struct session_settings
int cache_size;
int cache_expiry;
std::pair<int, int> outgoing_ports;
+ char peer_tos;
};
user_agent this is the client identification to the tracker.
@@ -2768,6 +2769,10 @@ used to bind outgoing sockets to. This may be useful for users whose router
allows them to assign QoS classes to traffic based on its local port. It is
a range instead of a single port because of the problems with failing to reconnect
to peers if a previous socket to that peer and port is in TIME_WAIT state.
+peer_tos determines the TOS byte set in the IP header of every packet
+sent to peers (including web seeds). The default value for this is 0x0
+(no marking). One potentially useful TOS mark is 0x20, this represents
+the QBone scavenger service. For more details, see QBSS.
diff --git a/docs/manual.rst b/docs/manual.rst
index d35581622..6f11f54ff 100644
--- a/docs/manual.rst
+++ b/docs/manual.rst
@@ -2605,6 +2605,7 @@ that will be sent to the tracker. The user-agent is a good way to identify your
int cache_size;
int cache_expiry;
std::pair
outgoing_ports;
+ char peer_tos;
};
``user_agent`` this is the client identification to the tracker.
@@ -2800,6 +2801,13 @@ allows them to assign QoS classes to traffic based on its local port. It is
a range instead of a single port because of the problems with failing to reconnect
to peers if a previous socket to that peer and port is in ``TIME_WAIT`` state.
+``peer_tos`` determines the TOS byte set in the IP header of every packet
+sent to peers (including web seeds). The default value for this is ``0x0``
+(no marking). One potentially useful TOS mark is ``0x20``, this represents
+the *QBone scavenger service*. For more details, see QBSS_.
+
+.. _`QBSS`: http://qbone.internet2.edu/qbss/
+
pe_settings
===========
diff --git a/include/libtorrent/proxy_base.hpp b/include/libtorrent/proxy_base.hpp
index c7a10d9a1..cdf5ff216 100644
--- a/include/libtorrent/proxy_base.hpp
+++ b/include/libtorrent/proxy_base.hpp
@@ -101,6 +101,20 @@ public:
m_sock.async_write_some(buffers, handler);
}
+#ifndef BOOST_NO_EXCEPTIONS
+ template
+ void set_option(SettableSocketOption const& opt)
+ {
+ m_sock.set_option(opt);
+ }
+#endif
+
+ template
+ asio::error_code set_option(SettableSocketOption const& opt, asio::error_code& ec)
+ {
+ return m_sock.set_option(opt, ec);
+ }
+
#ifndef BOOST_NO_EXCEPTIONS
void bind(endpoint_type const& endpoint)
{
diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp
index 5087a0f25..eb6fa35ca 100644
--- a/include/libtorrent/session_settings.hpp
+++ b/include/libtorrent/session_settings.hpp
@@ -127,6 +127,7 @@ namespace libtorrent
, cache_size(512)
, cache_expiry(60)
, outgoing_ports(0,0)
+ , peer_tos(0)
{}
// this is the user agent that will be sent to the tracker
@@ -339,6 +340,13 @@ namespace libtorrent
// is useful for users that have routers that
// allow QoS settings based on local port.
std::pair outgoing_ports;
+
+ // the TOS byte of all peer traffic (including
+ // web seeds) is set to this value. The default
+ // is the QBSS scavenger service
+ // http://qbone.internet2.edu/qbss/
+ // For unmarked packets, set to 0
+ char peer_tos;
};
#ifndef TORRENT_DISABLE_DHT
diff --git a/include/libtorrent/socket.hpp b/include/libtorrent/socket.hpp
index 2d829043e..704f7f171 100755
--- a/include/libtorrent/socket.hpp
+++ b/include/libtorrent/socket.hpp
@@ -185,6 +185,19 @@ namespace libtorrent
int m_value;
};
+ struct type_of_service
+ {
+ type_of_service(char val): m_value(val) {}
+ template
+ int level(Protocol const&) const { return IPPROTO_IP; }
+ template
+ int name(Protocol const&) const { return IP_TOS; }
+ template
+ char const* data(Protocol const&) const { return &m_value; }
+ template
+ size_t size(Protocol const&) const { return sizeof(m_value); }
+ char m_value;
+ };
}
#endif // TORRENT_SOCKET_HPP_INCLUDED
diff --git a/include/libtorrent/variant_stream.hpp b/include/libtorrent/variant_stream.hpp
index ff2f8f700..2daadbaa8 100644
--- a/include/libtorrent/variant_stream.hpp
+++ b/include/libtorrent/variant_stream.hpp
@@ -256,6 +256,45 @@ namespace aux
{ return EndpointType(); }
};
+// -------------- set_option -----------
+
+ template
+ struct set_option_visitor
+ : boost::static_visitor<>
+ {
+ set_option_visitor(SettableSocketOption const& opt)
+ : opt_(opt)
+ {}
+
+ template
+ void operator()(T* p) const
+ { p->set_option(opt_); }
+
+ std::size_t operator()(boost::blank) const {}
+
+ SettableSocketOption const& opt_;
+ };
+
+ template
+ struct set_option_visitor_ec
+ : boost::static_visitor
+ {
+ set_option_visitor_ec(SettableSocketOption const& opt, asio::error_code& ec)
+ : opt_(opt)
+ , ec_(ec)
+ {}
+
+ template
+ asio::error_code operator()(T* p) const
+ { return p->set_option(opt_, ec_); }
+
+ asio::error_code operator()(boost::blank) const
+ { return ec_; }
+
+ SettableSocketOption const& opt_;
+ asio::error_code& ec_;
+ };
+
// -------------- local_endpoint -----------
template
@@ -657,6 +696,22 @@ public:
);
}
+ template
+ void set_option(SettableSocketOption const& opt)
+ {
+ TORRENT_ASSERT(instantiated());
+ boost::apply_visitor(aux::set_option_visitor(opt)
+ , m_variant);
+ }
+
+ template
+ asio::error_code set_option(SettableSocketOption const& opt, asio::error_code& ec)
+ {
+ TORRENT_ASSERT(instantiated());
+ return boost::apply_visitor(aux::set_option_visitor_ec(opt, ec)
+ , m_variant);
+ }
+
endpoint_type local_endpoint() const
{
TORRENT_ASSERT(instantiated());
diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp
index 652776386..884998fc2 100755
--- a/src/peer_connection.cpp
+++ b/src/peer_connection.cpp
@@ -235,6 +235,9 @@ namespace libtorrent
(*m_logger) << "*** INCOMING CONNECTION\n";
#endif
+ if (m_remote.address().is_v4())
+ m_socket->set_option(type_of_service(ses.settings().peer_tos), ec);
+
#ifndef NDEBUG
piece_failed = false;
#endif
@@ -3011,6 +3014,12 @@ namespace libtorrent
<< " rtt = " << m_rtt << "\n";
#endif
+ if (m_remote.address().is_v4())
+ {
+ asio::error_code ec;
+ m_socket->set_option(type_of_service(m_ses.settings().peer_tos), ec);
+ }
+
on_connected();
setup_send();
setup_receive();