1 /* 2 3 Copyright (c) 2012-2018, Arvid Norberg 4 All rights reserved. 5 6 Redistribution and use in source and binary forms, with or without 7 modification, are permitted provided that the following conditions 8 are met: 9 10 * Redistributions of source code must retain the above copyright 11 notice, this list of conditions and the following disclaimer. 12 * Redistributions in binary form must reproduce the above copyright 13 notice, this list of conditions and the following disclaimer in 14 the documentation and/or other materials provided with the distribution. 15 * Neither the name of the author nor the names of its 16 contributors may be used to endorse or promote products derived 17 from this software without specific prior written permission. 18 19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 POSSIBILITY OF SUCH DAMAGE. 30 31 */ 32 33 #include "libtorrent/torrent_peer.hpp" 34 #include "libtorrent/assert.hpp" 35 #include "libtorrent/string_util.hpp" 36 #include "libtorrent/peer_connection.hpp" 37 #include "libtorrent/crc32c.hpp" 38 #include "libtorrent/ip_voter.hpp" 39 #include "libtorrent/io.hpp" // for write_uint16 40 41 namespace libtorrent { 42 43 namespace { 44 apply_mask(std::uint8_t * b,std::uint8_t const * mask,int size)45 void apply_mask(std::uint8_t* b, std::uint8_t const* mask, int size) 46 { 47 for (int i = 0; i < size; ++i) 48 { 49 *b &= *mask; 50 ++b; 51 ++mask; 52 } 53 } 54 } 55 56 // 1. if the IP addresses are identical, hash the ports in 16 bit network-order 57 // binary representation, ordered lowest first. 58 // 2. if the IPs are in the same /24, hash the IPs ordered, lowest first. 59 // 3. if the IPs are in the ame /16, mask the IPs by 0xffffff55, hash them 60 // ordered, lowest first. 61 // 4. if IPs are not in the same /16, mask the IPs by 0xffff5555, hash them 62 // ordered, lowest first. 63 // 64 // * for IPv6 peers, just use the first 64 bits and widen the masks. 65 // like this: 0xffff5555 -> 0xffffffff55555555 66 // the lower 64 bits are always unmasked 67 // 68 // * for IPv6 addresses, compare /32 and /48 instead of /16 and /24 69 // 70 // * the two IP addresses that are used to calculate the rank must 71 // always be of the same address family 72 // 73 // * all IP addresses are in network byte order when hashed peer_priority(tcp::endpoint e1,tcp::endpoint e2)74 std::uint32_t peer_priority(tcp::endpoint e1, tcp::endpoint e2) 75 { 76 TORRENT_ASSERT(is_v4(e1) == is_v4(e2)); 77 78 using std::swap; 79 80 std::uint32_t ret; 81 if (e1.address() == e2.address()) 82 { 83 if (e1.port() > e2.port()) 84 swap(e1, e2); 85 std::uint32_t p; 86 auto ptr = reinterpret_cast<char*>(&p); 87 detail::write_uint16(e1.port(), ptr); 88 detail::write_uint16(e2.port(), ptr); 89 ret = crc32c_32(p); 90 } 91 else if (is_v6(e1)) 92 { 93 static const std::uint8_t v6mask[][8] = { 94 { 0xff, 0xff, 0xff, 0xff, 0x55, 0x55, 0x55, 0x55 }, 95 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x55, 0x55 }, 96 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } 97 }; 98 99 if (e1 > e2) swap(e1, e2); 100 address_v6::bytes_type b1 = e1.address().to_v6().to_bytes(); 101 address_v6::bytes_type b2 = e2.address().to_v6().to_bytes(); 102 int const mask = std::memcmp(b1.data(), b2.data(), 4) ? 0 103 : std::memcmp(b1.data(), b2.data(), 6) ? 1 : 2; 104 apply_mask(b1.data(), v6mask[mask], 8); 105 apply_mask(b2.data(), v6mask[mask], 8); 106 std::uint64_t addrbuf[4]; 107 memcpy(&addrbuf[0], b1.data(), 16); 108 memcpy(&addrbuf[2], b2.data(), 16); 109 ret = crc32c(addrbuf, 4); 110 } 111 else 112 { 113 static const std::uint8_t v4mask[][4] = { 114 { 0xff, 0xff, 0x55, 0x55 }, 115 { 0xff, 0xff, 0xff, 0x55 }, 116 { 0xff, 0xff, 0xff, 0xff } 117 }; 118 119 if (e1 > e2) swap(e1, e2); 120 address_v4::bytes_type b1 = e1.address().to_v4().to_bytes(); 121 address_v4::bytes_type b2 = e2.address().to_v4().to_bytes(); 122 int mask = memcmp(&b1[0], &b2[0], 2) ? 0 123 : memcmp(&b1[0], &b2[0], 3) ? 1 : 2; 124 apply_mask(&b1[0], v4mask[mask], 4); 125 apply_mask(&b2[0], v4mask[mask], 4); 126 std::uint64_t addrbuf; 127 memcpy(&addrbuf, &b1[0], 4); 128 memcpy(reinterpret_cast<char*>(&addrbuf) + 4, &b2[0], 4); 129 ret = crc32c(&addrbuf, 1); 130 } 131 132 return ret; 133 } 134 torrent_peer(std::uint16_t port_,bool conn,peer_source_flags_t const src)135 torrent_peer::torrent_peer(std::uint16_t port_, bool conn 136 , peer_source_flags_t const src) 137 : prev_amount_upload(0) 138 , prev_amount_download(0) 139 , connection(nullptr) 140 , peer_rank(0) 141 , last_optimistically_unchoked(0) 142 , last_connected(0) 143 , port(port_) 144 , hashfails(0) 145 , failcount(0) 146 , connectable(conn) 147 , optimistically_unchoked(false) 148 , seed(false) 149 , fast_reconnects(0) 150 , trust_points(0) 151 , source(static_cast<std::uint8_t>(src)) 152 #if !defined TORRENT_DISABLE_ENCRYPTION 153 // assume no support in order to 154 // prefer opening non-encrypted 155 // connections. If it fails, we'll 156 // retry with encryption 157 , pe_support(false) 158 #endif 159 , is_v6_addr(false) 160 #if TORRENT_USE_I2P 161 , is_i2p_addr(false) 162 #endif 163 , on_parole(false) 164 , banned(false) 165 , supports_utp(true) // assume peers support utp 166 , confirmed_supports_utp(false) 167 , supports_holepunch(false) 168 , web_seed(false) 169 {} 170 rank(external_ip const & external,int external_port) const171 std::uint32_t torrent_peer::rank(external_ip const& external, int external_port) const 172 { 173 TORRENT_ASSERT(in_use); 174 //TODO: how do we deal with our external address changing? 175 if (peer_rank == 0) 176 peer_rank = peer_priority( 177 tcp::endpoint(external.external_address(this->address()), std::uint16_t(external_port)) 178 , tcp::endpoint(this->address(), this->port)); 179 return peer_rank; 180 } 181 182 #ifndef TORRENT_DISABLE_LOGGING to_string() const183 std::string torrent_peer::to_string() const 184 { 185 TORRENT_ASSERT(in_use); 186 #if TORRENT_USE_I2P 187 if (is_i2p_addr) return dest().to_string(); 188 #endif // TORRENT_USE_I2P 189 error_code ec; 190 return address().to_string(ec); 191 } 192 #endif 193 total_download() const194 std::int64_t torrent_peer::total_download() const 195 { 196 TORRENT_ASSERT(in_use); 197 if (connection != nullptr) 198 { 199 TORRENT_ASSERT(prev_amount_download == 0); 200 return connection->statistics().total_payload_download(); 201 } 202 else 203 { 204 return std::int64_t(prev_amount_download) << 10; 205 } 206 } 207 total_upload() const208 std::int64_t torrent_peer::total_upload() const 209 { 210 TORRENT_ASSERT(in_use); 211 if (connection != nullptr) 212 { 213 TORRENT_ASSERT(prev_amount_upload == 0); 214 return connection->statistics().total_payload_upload(); 215 } 216 else 217 { 218 return std::int64_t(prev_amount_upload) << 10; 219 } 220 } 221 ipv4_peer(tcp::endpoint const & ep,bool c,peer_source_flags_t const src)222 ipv4_peer::ipv4_peer(tcp::endpoint const& ep, bool c 223 , peer_source_flags_t const src) 224 : torrent_peer(ep.port(), c, src) 225 , addr(ep.address().to_v4()) 226 { 227 is_v6_addr = false; 228 #if TORRENT_USE_I2P 229 is_i2p_addr = false; 230 #endif 231 } 232 233 ipv4_peer::ipv4_peer(ipv4_peer const&) = default; 234 ipv4_peer& ipv4_peer::operator=(ipv4_peer const& p) = default; 235 236 #if TORRENT_USE_I2P i2p_peer(string_view dest,bool connectable_,peer_source_flags_t const src)237 i2p_peer::i2p_peer(string_view dest, bool connectable_ 238 , peer_source_flags_t const src) 239 : torrent_peer(0, connectable_, src) 240 , destination(dest) 241 { 242 is_v6_addr = false; 243 is_i2p_addr = true; 244 } 245 #endif // TORRENT_USE_I2P 246 ipv6_peer(tcp::endpoint const & ep,bool c,peer_source_flags_t const src)247 ipv6_peer::ipv6_peer(tcp::endpoint const& ep, bool c 248 , peer_source_flags_t const src) 249 : torrent_peer(ep.port(), c, src) 250 , addr(ep.address().to_v6().to_bytes()) 251 { 252 is_v6_addr = true; 253 #if TORRENT_USE_I2P 254 is_i2p_addr = false; 255 #endif 256 } 257 258 ipv6_peer::ipv6_peer(ipv6_peer const&) = default; 259 260 #if TORRENT_USE_I2P dest() const261 string_view torrent_peer::dest() const 262 { 263 if (is_i2p_addr) 264 return *static_cast<i2p_peer const*>(this)->destination; 265 return ""; 266 } 267 #endif 268 address() const269 libtorrent::address torrent_peer::address() const 270 { 271 if (is_v6_addr) 272 return libtorrent::address_v6( 273 static_cast<ipv6_peer const*>(this)->addr); 274 else 275 #if TORRENT_USE_I2P 276 if (is_i2p_addr) return libtorrent::address(); 277 else 278 #endif 279 return static_cast<ipv4_peer const*>(this)->addr; 280 } 281 282 } 283