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