merged utp_socket and simultaneous connections fix from RC_0_16
This commit is contained in:
parent
09d7a49ad7
commit
3555b01b85
|
@ -5,6 +5,8 @@
|
||||||
* fix uTP edge case where udp socket buffer fills up
|
* fix uTP edge case where udp socket buffer fills up
|
||||||
* fix nagle implementation in uTP
|
* fix nagle implementation in uTP
|
||||||
|
|
||||||
|
* consistently disconnect the same peer when two peers simultaneously connect
|
||||||
|
* fix local endpoint queries for uTP connections
|
||||||
* small optimization to local peer discovery to ignore our own broadcasts
|
* small optimization to local peer discovery to ignore our own broadcasts
|
||||||
* try harder to bind the udp socket (uTP, DHT, UDP-trackers, LSD) to the same port as TCP
|
* try harder to bind the udp socket (uTP, DHT, UDP-trackers, LSD) to the same port as TCP
|
||||||
* relax file timestamp requirements for accepting resume data
|
* relax file timestamp requirements for accepting resume data
|
||||||
|
|
|
@ -65,7 +65,8 @@ namespace libtorrent
|
||||||
|
|
||||||
void tick(ptime now);
|
void tick(ptime now);
|
||||||
|
|
||||||
tcp::endpoint local_endpoint(error_code& ec) const;
|
tcp::endpoint local_endpoint(address const& remote, error_code& ec) const;
|
||||||
|
int local_port(error_code& ec) const;
|
||||||
|
|
||||||
// flags for send_packet
|
// flags for send_packet
|
||||||
enum { dont_fragment = 1 };
|
enum { dont_fragment = 1 };
|
||||||
|
|
|
@ -871,20 +871,66 @@ namespace libtorrent
|
||||||
i->connection->disconnect(ec2);
|
i->connection->disconnect(ec2);
|
||||||
TORRENT_ASSERT(i->connection == 0);
|
TORRENT_ASSERT(i->connection == 0);
|
||||||
}
|
}
|
||||||
else if (!i->connection->is_connecting() || c.is_outgoing())
|
else if (i->connection->is_outgoing() == c.is_outgoing())
|
||||||
{
|
{
|
||||||
|
// if the other end connected to us both times, just drop
|
||||||
|
// the second one. Or if we made both connections.
|
||||||
c.disconnect(errors::duplicate_peer_id);
|
c.disconnect(errors::duplicate_peer_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
|
// at this point, we need to disconnect either
|
||||||
m_torrent->debug_log("duplicate connection. existing connection"
|
// i->connection or c. In order for both this client
|
||||||
" is connecting and this connection is incoming. closing existing "
|
// and the client on the other end to decide to
|
||||||
"connection in favour of this one");
|
// disconnect the same one, we need a consistent rule to
|
||||||
|
// select which one.
|
||||||
|
|
||||||
|
bool outgoing1 = c.is_outgoing();
|
||||||
|
|
||||||
|
// for this, we compare our endpoints (IP and port)
|
||||||
|
// and whoever has the lower IP,port should be the
|
||||||
|
// one keeping its outgoing connection. Since outgoing
|
||||||
|
// ports are selected at random by the OS, we need
|
||||||
|
// to be careful to only look at the target end of a
|
||||||
|
// connection for the endpoint.
|
||||||
|
|
||||||
|
tcp::endpoint our_ep = outgoing1 ? other_socket->local_endpoint(ec1) : this_socket->local_endpoint(ec1);
|
||||||
|
tcp::endpoint other_ep = outgoing1 ? this_socket->remote_endpoint(ec1) : other_socket->remote_endpoint(ec1);
|
||||||
|
|
||||||
|
if (our_ep < other_ep)
|
||||||
|
{
|
||||||
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
|
c.peer_log("*** DUPLICATE PEER RESOLUTION [ \"%s\" < \"%s\" ]"
|
||||||
|
, print_endpoint(our_ep).c_str(), print_endpoint(other_ep).c_str());
|
||||||
|
i->connection->peer_log("*** DUPLICATE PEER RESOLUTION [ \"%s\" < \"%s\" ]"
|
||||||
|
, print_endpoint(our_ep).c_str(), print_endpoint(other_ep).c_str());
|
||||||
#endif
|
#endif
|
||||||
i->connection->disconnect(errors::duplicate_peer_id);
|
|
||||||
TORRENT_ASSERT(i->connection == 0);
|
// we should keep our outgoing connection
|
||||||
|
if (!outgoing1)
|
||||||
|
{
|
||||||
|
c.disconnect(errors::duplicate_peer_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
i->connection->disconnect(errors::duplicate_peer_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
|
c.peer_log("*** DUPLICATE PEER RESOLUTION [ \"%s\" >= \"%s\" ]"
|
||||||
|
, print_endpoint(our_ep).c_str(), print_endpoint(other_ep).c_str());
|
||||||
|
i->connection->peer_log("*** DUPLICATE PEER RESOLUTION [ \"%s\" >= \"%s\" ]"
|
||||||
|
, print_endpoint(our_ep).c_str(), print_endpoint(other_ep).c_str());
|
||||||
|
#endif
|
||||||
|
// they should keep their outgoing connection
|
||||||
|
if (outgoing1)
|
||||||
|
{
|
||||||
|
c.disconnect(errors::duplicate_peer_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
i->connection->disconnect(errors::duplicate_peer_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -194,9 +194,55 @@ namespace libtorrent
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
tcp::endpoint utp_socket_manager::local_endpoint(error_code& ec) const
|
int utp_socket_manager::local_port(error_code& ec) const
|
||||||
{
|
{
|
||||||
return m_sock.local_endpoint(ec);
|
return m_sock.local_endpoint(ec).port();
|
||||||
|
}
|
||||||
|
|
||||||
|
tcp::endpoint utp_socket_manager::local_endpoint(address const& remote, error_code& ec) const
|
||||||
|
{
|
||||||
|
tcp::endpoint socket_ep = m_sock.local_endpoint(ec);
|
||||||
|
|
||||||
|
// first enumerate the routes in the routing table
|
||||||
|
std::vector<ip_route> routes = enum_routes(m_sock.get_io_service(), ec);
|
||||||
|
if (ec) return socket_ep;
|
||||||
|
|
||||||
|
if (routes.empty()) return socket_ep;
|
||||||
|
// then find the best match
|
||||||
|
ip_route* best = &routes[0];
|
||||||
|
for (std::vector<ip_route>::iterator i = routes.begin()
|
||||||
|
, end(routes.end()); i != end; ++i)
|
||||||
|
{
|
||||||
|
if (is_any(i->destination) && i->destination.is_v4() == remote.is_v4())
|
||||||
|
{
|
||||||
|
best = &*i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match_addr_mask(remote, i->destination, i->netmask))
|
||||||
|
{
|
||||||
|
best = &*i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// best now tells us which interface we would send over
|
||||||
|
// for this target. Now figure out what the local address
|
||||||
|
// is for that interface
|
||||||
|
|
||||||
|
std::vector<ip_interface> net = enum_net_interfaces(m_sock.get_io_service(), ec);
|
||||||
|
if (ec) return socket_ep;
|
||||||
|
|
||||||
|
for (std::vector<ip_interface>::iterator i = net.begin()
|
||||||
|
, end(net.end()); i != end; ++i)
|
||||||
|
{
|
||||||
|
if (i->interface_address.is_v4() != remote.is_v4())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strcmp(best->name, i->name) == 0)
|
||||||
|
return tcp::endpoint(i->interface_address, socket_ep.port());
|
||||||
|
}
|
||||||
|
return socket_ep;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool utp_socket_manager::incoming_packet(error_code const& ec, udp::endpoint const& ep
|
bool utp_socket_manager::incoming_packet(error_code const& ec, udp::endpoint const& ep
|
||||||
|
|
|
@ -398,6 +398,9 @@ struct utp_socket_impl
|
||||||
// the address of the remote endpoint
|
// the address of the remote endpoint
|
||||||
address m_remote_address;
|
address m_remote_address;
|
||||||
|
|
||||||
|
// the local address
|
||||||
|
address m_local_address;
|
||||||
|
|
||||||
// the send and receive buffers
|
// the send and receive buffers
|
||||||
// maps packet sequence numbers
|
// maps packet sequence numbers
|
||||||
packet_buffer m_inbuf;
|
packet_buffer m_inbuf;
|
||||||
|
@ -789,7 +792,7 @@ utp_stream::endpoint_type utp_stream::local_endpoint(error_code& ec) const
|
||||||
ec = asio::error::not_connected;
|
ec = asio::error::not_connected;
|
||||||
return endpoint_type();
|
return endpoint_type();
|
||||||
}
|
}
|
||||||
return m_impl->m_sm->local_endpoint(ec);
|
return tcp::endpoint(m_impl->m_local_address, m_impl->m_sm->local_port(ec));
|
||||||
}
|
}
|
||||||
|
|
||||||
utp_stream::~utp_stream()
|
utp_stream::~utp_stream()
|
||||||
|
@ -1063,6 +1066,9 @@ void utp_stream::do_connect(tcp::endpoint const& ep, utp_stream::connect_handler
|
||||||
m_impl->m_port = ep.port();
|
m_impl->m_port = ep.port();
|
||||||
m_impl->m_connect_handler = handler;
|
m_impl->m_connect_handler = handler;
|
||||||
|
|
||||||
|
error_code ec;
|
||||||
|
m_impl->m_local_address = m_impl->m_sm->local_endpoint(m_impl->m_remote_address, ec).address();
|
||||||
|
|
||||||
if (m_impl->test_socket_state()) return;
|
if (m_impl->test_socket_state()) return;
|
||||||
m_impl->send_syn();
|
m_impl->send_syn();
|
||||||
}
|
}
|
||||||
|
@ -2710,6 +2716,9 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
||||||
m_remote_address = ep.address();
|
m_remote_address = ep.address();
|
||||||
m_port = ep.port();
|
m_port = ep.port();
|
||||||
|
|
||||||
|
error_code ec;
|
||||||
|
m_local_address = m_sm->local_endpoint(m_remote_address, ec).address();
|
||||||
|
|
||||||
m_ack_nr = ph->seq_nr;
|
m_ack_nr = ph->seq_nr;
|
||||||
m_seq_nr = random();
|
m_seq_nr = random();
|
||||||
m_acked_seq_nr = (m_seq_nr - 1) & ACK_MASK;
|
m_acked_seq_nr = (m_seq_nr - 1) & ACK_MASK;
|
||||||
|
|
Loading…
Reference in New Issue