lt sync 2240

This commit is contained in:
Andrew Resch 2008-04-29 21:49:24 +00:00
parent 88c20df380
commit 85f557e6c1
10 changed files with 366 additions and 138 deletions

View File

@ -509,6 +509,10 @@ namespace libtorrent
// port we'll bind the next outgoing socket to
int m_next_port;
// the sequence number to assign to the
// next torrent that's added
int m_torrent_sequence;
#ifndef TORRENT_DISABLE_DHT
boost::intrusive_ptr<dht::dht_tracker> m_dht;
dht_settings m_dht_settings;
@ -522,10 +526,6 @@ namespace libtorrent
// but for the udp port used by the DHT.
int m_external_udp_port;
// the sequence number to assign to the
// next torrent that's added
int m_torrent_sequence;
udp_socket m_dht_socket;
void on_receive_udp(asio::error_code const& e

View File

@ -43,6 +43,15 @@ namespace libtorrent
{
address interface_address;
address netmask;
char name[32];
};
struct ip_route
{
address destination;
address netmask;
address gateway;
char name[32];
};
// returns a list of the configured IP interfaces
@ -50,6 +59,8 @@ namespace libtorrent
TORRENT_EXPORT std::vector<ip_interface> enum_net_interfaces(asio::io_service& ios
, asio::error_code& ec);
TORRENT_EXPORT std::vector<ip_route> enum_routes(asio::io_service& ios, asio::error_code& ec);
// returns true if the specified address is on the same
// local network as the specified interface
TORRENT_EXPORT bool in_subnet(address const& addr, ip_interface const& iface);
@ -59,7 +70,7 @@ namespace libtorrent
TORRENT_EXPORT bool in_local_network(asio::io_service& ios, address const& addr
, asio::error_code& ec);
TORRENT_EXPORT address get_default_gateway(asio::io_service& ios, address const& addr
TORRENT_EXPORT address get_default_gateway(asio::io_service& ios
, asio::error_code& ec);
}

View File

@ -267,10 +267,6 @@ namespace libtorrent
bool compare_peer(policy::peer const& lhs, policy::peer const& rhs
, address const& external_ip) const;
// since the peer list can grow too large
// to scan all of it, start at this iterator
iterator m_round_robin;
iterator find_disconnect_candidate();
iterator find_connect_candidate();
@ -278,6 +274,10 @@ namespace libtorrent
std::multimap<address, peer> m_peers;
// since the peer list can grow too large
// to scan all of it, start at this iterator
iterator m_round_robin;
torrent* m_torrent;
// free download we have got that hasn't

View File

@ -256,7 +256,7 @@ namespace libtorrent
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
#include <windows.h>
#include "libtorrent/assert.hpp"
namespace libtorrent

View File

@ -34,8 +34,8 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_VERSION_HPP_INCLUDED
#define LIBTORRENT_VERSION_MAJOR 0
#define LIBTORRENT_VERSION_MINOR 13
#define LIBTORRENT_VERSION_MINOR 14
#define LIBTORRENT_VERSION "0.13.0.0"
#define LIBTORRENT_VERSION "0.14.0.0"
#endif

View File

@ -31,14 +31,24 @@ POSSIBILITY OF SUCH DAMAGE.
*/
#include "libtorrent/config.hpp"
#include <boost/bind.hpp>
#include <vector>
#include "libtorrent/enum_net.hpp"
#include "libtorrent/broadcast_socket.hpp"
#include <asio/ip/host_name.hpp>
#if defined TORRENT_BSD || defined TORRENT_LINUX
#if defined TORRENT_BSD
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <net/route.h>
#elif defined TORRENT_WINDOWS
#include <sys/sysctl.h>
#include <boost/scoped_array.hpp>
#endif
#if defined TORRENT_WINDOWS
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
@ -46,33 +56,147 @@ POSSIBILITY OF SUCH DAMAGE.
#include <iphlpapi.h>
#endif
#include "libtorrent/enum_net.hpp"
#include "libtorrent/broadcast_socket.hpp"
#include <asio/ip/host_name.hpp>
#if defined TORRENT_LINUX
#include <asm/types.h>
#include <netinet/ether.h>
#include <netinet/in.h>
#include <net/if.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#endif
namespace libtorrent
namespace libtorrent { namespace
{
namespace
{
address sockaddr_to_address(sockaddr const* sin)
{
if (sin->sa_family == AF_INET)
address inaddr_to_address(in_addr const* ina)
{
typedef asio::ip::address_v4::bytes_type bytes_t;
bytes_t b;
memcpy(&b[0], &((sockaddr_in const*)sin)->sin_addr, b.size());
memcpy(&b[0], ina, b.size());
return address_v4(b);
}
else if (sin->sa_family == AF_INET6)
address inaddr6_to_address(in6_addr const* ina6)
{
typedef asio::ip::address_v6::bytes_type bytes_t;
bytes_t b;
memcpy(&b[0], &((sockaddr_in6 const*)sin)->sin6_addr, b.size());
memcpy(&b[0], ina6, b.size());
return address_v6(b);
}
address sockaddr_to_address(sockaddr const* sin)
{
if (sin->sa_family == AF_INET)
return inaddr_to_address(&((sockaddr_in const*)sin)->sin_addr);
else if (sin->sa_family == AF_INET6)
return inaddr6_to_address(&((sockaddr_in6 const*)sin)->sin6_addr);
return address();
}
#if defined TORRENT_LINUX
int read_nl_sock(int sock, char *buf, int bufsize, int seq, int pid)
{
nlmsghdr* nl_hdr;
int msg_len = 0;
do
{
int read_len = recv(sock, buf, bufsize - msg_len, 0);
if (read_len < 0) return -1;
nl_hdr = (nlmsghdr*)buf;
if ((NLMSG_OK(nl_hdr, read_len) == 0) || (nl_hdr->nlmsg_type == NLMSG_ERROR))
return -1;
if (nl_hdr->nlmsg_type == NLMSG_DONE) break;
buf += read_len;
msg_len += read_len;
if ((nl_hdr->nlmsg_flags & NLM_F_MULTI) == 0) break;
} while((nl_hdr->nlmsg_seq != seq) || (nl_hdr->nlmsg_pid != pid));
return msg_len;
}
bool parse_route(nlmsghdr* nl_hdr, ip_route* rt_info)
{
rtmsg* rt_msg = (rtmsg*)NLMSG_DATA(nl_hdr);
if((rt_msg->rtm_family != AF_INET) || (rt_msg->rtm_table != RT_TABLE_MAIN))
return false;
int rt_len = RTM_PAYLOAD(nl_hdr);
for (rtattr* rt_attr = (rtattr*)RTM_RTA(rt_msg);
RTA_OK(rt_attr,rt_len); rt_attr = RTA_NEXT(rt_attr,rt_len))
{
switch(rt_attr->rta_type)
{
case RTA_OIF:
if_indextoname(*(int*)RTA_DATA(rt_attr), rt_info->name);
break;
case RTA_GATEWAY:
rt_info->gateway = address_v4(*(u_int*)RTA_DATA(rt_attr));
break;
case RTA_DST:
rt_info->destination = address_v4(*(u_int*)RTA_DATA(rt_attr));
break;
}
}
return true;
}
#endif
#if defined TORRENT_BSD
bool parse_route(rt_msghdr* rtm, ip_route* rt_info)
{
sockaddr* rti_info[RTAX_MAX];
sockaddr* sa = (sockaddr*)(rtm + 1);
for (int i = 0; i < RTAX_MAX; ++i)
{
if ((rtm->rtm_addrs & (1 << i)) == 0)
{
rti_info[i] = 0;
continue;
}
rti_info[i] = sa;
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
sa = (sockaddr*)((char*)(sa) + ROUNDUP(sa->sa_len));
#undef ROUNDUP
}
sa = rti_info[RTAX_GATEWAY];
if (sa == 0
|| rti_info[RTAX_DST] == 0
|| rti_info[RTAX_NETMASK] == 0
|| (sa->sa_family != AF_INET && sa->sa_family != AF_INET6))
return false;
rt_info->gateway = sockaddr_to_address(rti_info[RTAX_GATEWAY]);
rt_info->netmask = sockaddr_to_address(rti_info[RTAX_NETMASK]);
rt_info->destination = sockaddr_to_address(rti_info[RTAX_DST]);
if_indextoname(rtm->rtm_index, rt_info->name);
return true;
}
#endif
#ifdef TORRENT_BSD
bool verify_sockaddr(sockaddr_in* sin)
{
@ -83,7 +207,10 @@ namespace libtorrent
}
#endif
}
}} // <anonymous>
namespace libtorrent
{
bool in_subnet(address const& addr, ip_interface const& iface)
{
@ -144,6 +271,7 @@ namespace libtorrent
{
ip_interface iface;
iface.interface_address = sockaddr_to_address(&item.ifr_addr);
strcpy(iface.name, item.ifr_name);
ifreq netmask = item;
if (ioctl(s, SIOCGIFNETMASK, &netmask) < 0)
@ -205,6 +333,7 @@ namespace libtorrent
{
iface.interface_address = sockaddr_to_address(&buffer[i].iiAddress.Address);
iface.netmask = sockaddr_to_address(&buffer[i].iiNetmask.Address);
iface.name[0] = 0;
if (iface.interface_address == address_v4::any()) continue;
ret.push_back(iface);
}
@ -227,11 +356,21 @@ namespace libtorrent
return ret;
}
address get_default_gateway(asio::io_service& ios, address const& interface, asio::error_code& ec)
address get_default_gateway(asio::io_service& ios, asio::error_code& ec)
{
std::vector<ip_route> ret = enum_routes(ios, ec);
std::vector<ip_route>::iterator i = std::find_if(ret.begin(), ret.end()
, boost::bind(&ip_route::destination, _1) == address());
if (i == ret.end()) return address();
return i->gateway;
}
std::vector<ip_route> enum_routes(asio::io_service& ios, asio::error_code& ec)
{
std::vector<ip_route> ret;
#if defined TORRENT_BSD
/*
struct rt_msg
{
rt_msghdr m_rtm;
@ -244,15 +383,15 @@ namespace libtorrent
m.m_rtm.rtm_type = RTM_GET;
m.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
m.m_rtm.rtm_version = RTM_VERSION;
m.m_rtm.rtm_addrs = RTA_DST | RTA_GATEWAY;
m.m_rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
m.m_rtm.rtm_seq = 0;
m.m_rtm.rtm_msglen = len;
int s = socket(PF_ROUTE, SOCK_RAW, AF_INET);
int s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
if (s == -1)
{
ec = asio::error_code(errno, asio::error::system_category);
return address_v4::any();
return std::vector<ip_route>();
}
int n = write(s, &m, len);
@ -260,13 +399,13 @@ namespace libtorrent
{
ec = asio::error_code(errno, asio::error::system_category);
close(s);
return address_v4::any();
return std::vector<ip_route>();
}
else if (n != len)
{
ec = asio::error::operation_not_supported;
close(s);
return address_v4::any();
return std::vector<ip_route>();
}
bzero(&m, len);
@ -275,16 +414,17 @@ namespace libtorrent
{
ec = asio::error_code(errno, asio::error::system_category);
close(s);
return address_v4::any();
return std::vector<ip_route>();
}
close(s);
TORRENT_ASSERT(m.m_rtm.rtm_seq == 0);
TORRENT_ASSERT(m.m_rtm.rtm_pid == getpid());
if (m.m_rtm.rtm_errno)
for (rt_msghdr* ptr = &m.m_rtm; (char*)ptr < ((char*)&m.m_rtm) + n; ptr = (rt_msghdr*)(((char*)ptr) + ptr->rtm_msglen))
{
ec = asio::error_code(m.m_rtm.rtm_errno, asio::error::system_category);
return address_v4::any();
std::cout << " rtm_msglen: " << ptr->rtm_msglen << std::endl;
std::cout << " rtm_type: " << ptr->rtm_type << std::endl;
if (ptr->rtm_errno)
{
ec = asio::error_code(ptr->rtm_errno, asio::error::system_category);
return std::vector<ip_route>();
}
if (m.m_rtm.rtm_flags & RTF_UP == 0
|| m.m_rtm.rtm_flags & RTF_GATEWAY == 0)
@ -292,43 +432,83 @@ namespace libtorrent
ec = asio::error::operation_not_supported;
return address_v4::any();
}
if (m.m_rtm.rtm_addrs & RTA_DST == 0
|| m.m_rtm.rtm_addrs & RTA_GATEWAY == 0)
if (ptr->rtm_addrs & RTA_DST == 0
|| ptr->rtm_addrs & RTA_GATEWAY == 0
|| ptr->rtm_addrs & RTA_NETMASK == 0)
{
ec = asio::error::operation_not_supported;
return address_v4::any();
return std::vector<ip_route>();
}
if (m.m_rtm.rtm_msglen > len)
if (ptr->rtm_msglen > len - ((char*)ptr - ((char*)&m.m_rtm)))
{
ec = asio::error::operation_not_supported;
return address_v4::any();
return std::vector<ip_route>();
}
int min_len = sizeof(rt_msghdr) + 2 * sizeof(struct sockaddr_in);
int min_len = sizeof(rt_msghdr) + 2 * sizeof(sockaddr_in);
if (m.m_rtm.rtm_msglen < min_len)
{
ec = asio::error::operation_not_supported;
return address_v4::any();
return std::vector<ip_route>();
}
// default route
ip_route r;
// destination
char* p = m.buf;
sockaddr_in* sin = (sockaddr_in*)p;
if (!verify_sockaddr(sin))
{
ec = asio::error::operation_not_supported;
return address_v4::any();
}
r.destination = sockaddr_to_address((sockaddr*)p);
// default gateway
// gateway
p += sin->sin_len;
sin = (sockaddr_in*)p;
if (!verify_sockaddr(sin))
r.gateway = sockaddr_to_address((sockaddr*)p);
// netmask
p += sin->sin_len;
sin = (sockaddr_in*)p;
r.netmask = sockaddr_to_address((sockaddr*)p);
ret.push_back(r);
}
close(s);
*/
int mib[6] = { CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_DUMP, 0};
size_t needed = 0;
if (sysctl(mib, 6, 0, &needed, 0, 0) < 0)
{
ec = asio::error::operation_not_supported;
return address_v4::any();
ec = asio::error_code(errno, asio::error::system_category);
return std::vector<ip_route>();
}
return sockaddr_to_address((sockaddr*)sin);
if (needed <= 0)
{
return std::vector<ip_route>();
}
boost::scoped_array<char> buf(new (std::nothrow) char[needed]);
if (buf.get() == 0)
{
ec = asio::error::no_memory;
return std::vector<ip_route>();
}
if (sysctl(mib, 6, buf.get(), &needed, 0, 0) < 0)
{
ec = asio::error_code(errno, asio::error::system_category);
return std::vector<ip_route>();
}
char* end = buf.get() + needed;
rt_msghdr* rtm;
for (char* next = buf.get(); next < end; next += rtm->rtm_msglen)
{
rtm = (rt_msghdr*)next;
if (rtm->rtm_version != RTM_VERSION)
continue;
ip_route r;
if (parse_route(rtm, &r)) ret.push_back(r);
}
#elif defined TORRENT_WINDOWS
@ -337,7 +517,7 @@ namespace libtorrent
if (!iphlp)
{
ec = asio::error::operation_not_supported;
return address_v4::any();
return std::vector<ip_route>();
}
// Get GetAdaptersInfo() pointer
@ -347,7 +527,7 @@ namespace libtorrent
{
FreeLibrary(iphlp);
ec = asio::error::operation_not_supported;
return address_v4::any();
return std::vector<ip_route>();
}
PIP_ADAPTER_INFO adapter_info = 0;
@ -356,7 +536,7 @@ namespace libtorrent
{
FreeLibrary(iphlp);
ec = asio::error::operation_not_supported;
return address_v4::any();
return std::vector<ip_route>();
}
adapter_info = (IP_ADAPTER_INFO*)malloc(out_buf_size);
@ -364,7 +544,7 @@ namespace libtorrent
{
FreeLibrary(iphlp);
ec = asio::error::no_memory;
return address_v4::any();
return std::vector<ip_route>();
}
address ret;
@ -373,18 +553,19 @@ namespace libtorrent
for (PIP_ADAPTER_INFO adapter = adapter_info;
adapter != 0; adapter = adapter->Next)
{
address iface = address::from_string(adapter->IpAddressList.IpAddress.String, ec);
ip_route r;
r.source = address::from_string(adapter->IpAddressList.IpAddress.String, ec);
r.gateway = address::from_string(adapter->GatewayList.IpAddress.String, ec);
r.netmask = address::from_string(adapter->IpAddressList.IpMask.String, ec);
strcpy(r.name, adapter->AdapterName);
if (ec)
{
ec = asio::error_code();
continue;
}
if (is_loopback(iface) || is_any(iface)) continue;
if (interface == address() || interface == iface)
{
ret = address::from_string(adapter->GatewayList.IpAddress.String, ec);
break;
}
ret.push_back(r);
}
}
@ -394,16 +575,53 @@ namespace libtorrent
return ret;
//#elif defined TORRENT_LINUX
// No linux implementation yet
#else
if (!interface.is_v4())
#elif defined TORRENT_LINUX
enum { BUFSIZE = 8192 };
int sock = socket(PF_ROUTE, SOCK_DGRAM, NETLINK_ROUTE);
if (sock < 0)
{
ec = asio::error::operation_not_supported;
return address_v4::any();
ec = asio::error_code(errno, asio::error::system_category);
return std::vector<ip_route>();
}
return address_v4((interface.to_v4().to_ulong() & 0xffffff00) | 1);
int seq = 0;
char msg[BUFSIZE];
memset(msg, 0, BUFSIZE);
nlmsghdr* nl_msg = (nlmsghdr*)msg;
nl_msg->nlmsg_len = NLMSG_LENGTH(sizeof(rtmsg));
nl_msg->nlmsg_type = RTM_GETROUTE;
nl_msg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
nl_msg->nlmsg_seq = seq++;
nl_msg->nlmsg_pid = getpid();
if (send(sock, nl_msg, nl_msg->nlmsg_len, 0) < 0)
{
ec = asio::error_code(errno, asio::error::system_category);
close(sock);
return std::vector<ip_route>();
}
int len = read_nl_sock(sock, msg, BUFSIZE, seq, getpid());
if (len < 0)
{
ec = asio::error_code(errno, asio::error::system_category);
close(sock);
return std::vector<ip_route>();
}
for (; NLMSG_OK(nl_msg, len); nl_msg = NLMSG_NEXT(nl_msg, len))
{
ip_route r;
if (parse_route(nl_msg, &r)) ret.push_back(r);
}
close(sock);
#endif
return ret;
}
}

View File

@ -64,7 +64,7 @@ void natpmp::rebind(address const& listen_interface)
mutex_t::scoped_lock l(m_mutex);
asio::error_code ec;
address gateway = get_default_gateway(m_socket.get_io_service(), listen_interface, ec);
address gateway = get_default_gateway(m_socket.get_io_service(), ec);
if (ec)
{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)

View File

@ -1415,6 +1415,7 @@ namespace libtorrent
return;
}
disk_buffer_holder holder(m_ses, buffer);
std::memcpy(buffer, data, p.length);
incoming_piece(p, holder);
}

View File

@ -344,7 +344,8 @@ namespace libtorrent
}
policy::policy(torrent* t)
: m_torrent(t)
: m_round_robin(m_peers.end())
, m_torrent(t)
, m_available_free_upload(0)
, m_num_connect_candidates(0)
{ TORRENT_ASSERT(t); }
@ -484,8 +485,7 @@ namespace libtorrent
external_ip = address_v4(bytes);
}
if (m_round_robin == iterator() || m_round_robin == m_peers.end())
m_round_robin = m_peers.begin();
if (m_round_robin == m_peers.end()) m_round_robin = m_peers.begin();
for (int iterations = (std::min)(int(m_peers.size()), 300);
iterations > 0; ++m_round_robin, --iterations)
@ -1330,26 +1330,24 @@ namespace libtorrent
, address const& external_ip) const
{
// prefer peers with lower failcount
if (lhs.failcount < rhs.failcount) return true;
if (lhs.failcount > rhs.failcount) return false;
if (lhs.failcount != rhs.failcount)
return lhs.failcount < rhs.failcount;
// Local peers should always be tried first
bool lhs_local = is_local(lhs.ip.address());
bool rhs_local = is_local(rhs.ip.address());
if (lhs_local && !rhs_local) return true;
if (!lhs_local && rhs_local) return false;
if (lhs_local != rhs_local) return lhs_local > rhs_local;
if (lhs.connected < rhs.connected) return true;
if (lhs.connected > rhs.connected) return false;
if (lhs.connected != rhs.connected)
return lhs.connected < rhs.connected;
#ifndef TORRENT_DISABLE_GEO_IP
// don't bias fast peers when seeding
if (!m_torrent->is_finished() && m_torrent->session().has_asnum_db())
{
std::pair<const int, int>* lhs_as = lhs.inet_as;
std::pair<const int, int>* rhs_as = rhs.inet_as;
if (lhs_as ? lhs_as->second : 0 > rhs_as ? rhs_as->second : 0) return true;
if (lhs_as ? lhs_as->second : 0 < rhs_as ? rhs_as->second : 0) return false;
int lhs_as = lhs.inet_as ? lhs.inet_as->second : 0;
int rhs_as = rhs.inet_as ? rhs.inet_as->second : 0;
if (lhs_as != rhs_as) return lhs_as > rhs_as;
}
#endif
int lhs_distance = cidr_distance(external_ip, lhs.ip.address());

View File

@ -164,10 +164,10 @@ namespace aux {
, m_disconnect_time_scaler(90)
, m_incoming_connection(false)
, m_last_tick(time_now())
, m_torrent_sequence(0)
#ifndef TORRENT_DISABLE_DHT
, m_dht_same_port(true)
, m_external_udp_port(0)
, m_torrent_sequence(0)
, m_dht_socket(m_io_service, bind(&session_impl::on_receive_udp, this, _1, _2, _3, _4)
, m_half_open)
#endif