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