forked from premiere/premiere-libtorrent
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 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
|
||||
* 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
|
||||
|
|
|
@ -65,7 +65,8 @@ namespace libtorrent
|
|||
|
||||
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
|
||||
enum { dont_fragment = 1 };
|
||||
|
|
|
@ -871,20 +871,66 @@ namespace libtorrent
|
|||
i->connection->disconnect(ec2);
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
|
||||
m_torrent->debug_log("duplicate connection. existing connection"
|
||||
" is connecting and this connection is incoming. closing existing "
|
||||
"connection in favour of this one");
|
||||
// at this point, we need to disconnect either
|
||||
// i->connection or c. In order for both this client
|
||||
// and the client on the other end to decide to
|
||||
// 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
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -398,6 +398,9 @@ struct utp_socket_impl
|
|||
// the address of the remote endpoint
|
||||
address m_remote_address;
|
||||
|
||||
// the local address
|
||||
address m_local_address;
|
||||
|
||||
// the send and receive buffers
|
||||
// maps packet sequence numbers
|
||||
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;
|
||||
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()
|
||||
|
@ -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_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;
|
||||
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_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_seq_nr = random();
|
||||
m_acked_seq_nr = (m_seq_nr - 1) & ACK_MASK;
|
||||
|
|
Loading…
Reference in New Issue