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 , maybe_upload_only(false) 150 , fast_reconnects(0) 151 , trust_points(0) 152 , source(static_cast<std::uint8_t>(src)) 153 #if !defined TORRENT_DISABLE_ENCRYPTION 154 // assume no support in order to 155 // prefer opening non-encrypted 156 // connections. If it fails, we'll 157 // retry with encryption 158 , pe_support(false) 159 #endif 160 , is_v6_addr(false) 161 #if TORRENT_USE_I2P 162 , is_i2p_addr(false) 163 #endif 164 , on_parole(false) 165 , banned(false) 166 , supports_utp(true) // assume peers support utp 167 , confirmed_supports_utp(false) 168 , supports_holepunch(false) 169 , web_seed(false) 170 {} 171 rank(external_ip const & external,int external_port) const172 std::uint32_t torrent_peer::rank(external_ip const& external, int external_port) const 173 { 174 TORRENT_ASSERT(in_use); 175 //TODO: how do we deal with our external address changing? 176 if (peer_rank == 0) 177 peer_rank = peer_priority( 178 tcp::endpoint(external.external_address(this->address()), std::uint16_t(external_port)) 179 , tcp::endpoint(this->address(), this->port)); 180 return peer_rank; 181 } 182 183 #ifndef TORRENT_DISABLE_LOGGING to_string() const184 std::string torrent_peer::to_string() const 185 { 186 TORRENT_ASSERT(in_use); 187 #if TORRENT_USE_I2P 188 if (is_i2p_addr) return dest().to_string(); 189 #endif // TORRENT_USE_I2P 190 error_code ec; 191 return address().to_string(ec); 192 } 193 #endif 194 total_download() const195 std::int64_t torrent_peer::total_download() const 196 { 197 TORRENT_ASSERT(in_use); 198 if (connection != nullptr) 199 { 200 TORRENT_ASSERT(prev_amount_download == 0); 201 return connection->statistics().total_payload_download(); 202 } 203 else 204 { 205 return std::int64_t(prev_amount_download) << 10; 206 } 207 } 208 total_upload() const209 std::int64_t torrent_peer::total_upload() const 210 { 211 TORRENT_ASSERT(in_use); 212 if (connection != nullptr) 213 { 214 TORRENT_ASSERT(prev_amount_upload == 0); 215 return connection->statistics().total_payload_upload(); 216 } 217 else 218 { 219 return std::int64_t(prev_amount_upload) << 10; 220 } 221 } 222 ipv4_peer(tcp::endpoint const & ep,bool c,peer_source_flags_t const src)223 ipv4_peer::ipv4_peer(tcp::endpoint const& ep, bool c 224 , peer_source_flags_t const src) 225 : torrent_peer(ep.port(), c, src) 226 , addr(ep.address().to_v4()) 227 { 228 is_v6_addr = false; 229 #if TORRENT_USE_I2P 230 is_i2p_addr = false; 231 #endif 232 } 233 234 ipv4_peer::ipv4_peer(ipv4_peer const&) = default; 235 ipv4_peer& ipv4_peer::operator=(ipv4_peer const& p) = default; 236 237 #if TORRENT_USE_I2P i2p_peer(string_view dest,bool connectable_,peer_source_flags_t const src)238 i2p_peer::i2p_peer(string_view dest, bool connectable_ 239 , peer_source_flags_t const src) 240 : torrent_peer(0, connectable_, src) 241 , destination(dest) 242 { 243 is_v6_addr = false; 244 is_i2p_addr = true; 245 } 246 #endif // TORRENT_USE_I2P 247 ipv6_peer(tcp::endpoint const & ep,bool c,peer_source_flags_t const src)248 ipv6_peer::ipv6_peer(tcp::endpoint const& ep, bool c 249 , peer_source_flags_t const src) 250 : torrent_peer(ep.port(), c, src) 251 , addr(ep.address().to_v6().to_bytes()) 252 { 253 is_v6_addr = true; 254 #if TORRENT_USE_I2P 255 is_i2p_addr = false; 256 #endif 257 } 258 259 ipv6_peer::ipv6_peer(ipv6_peer const&) = default; 260 261 #if TORRENT_USE_I2P dest() const262 string_view torrent_peer::dest() const 263 { 264 if (is_i2p_addr) 265 return *static_cast<i2p_peer const*>(this)->destination; 266 return ""; 267 } 268 #endif 269 address() const270 libtorrent::address torrent_peer::address() const 271 { 272 if (is_v6_addr) 273 return libtorrent::address_v6( 274 static_cast<ipv6_peer const*>(this)->addr); 275 else 276 #if TORRENT_USE_I2P 277 if (is_i2p_addr) return libtorrent::address(); 278 else 279 #endif 280 return static_cast<ipv4_peer const*>(this)->addr; 281 } 282 283 } 284