1 /*
2 
3 Copyright (c) 2017, 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 "setup_swarm.hpp"
34 #include "test.hpp"
35 #include "utils.hpp"
36 #include "libtorrent/session.hpp"
37 #include "libtorrent/socket.hpp"
38 #include "libtorrent/alert_types.hpp"
39 #include "libtorrent/extensions.hpp"
40 #include "simulator/simulator.hpp"
41 #include "simulator/utils.hpp" // for timer
42 #include "settings.hpp"
43 #include "create_torrent.hpp"
44 #include "setup_transfer.hpp" // for addr()
45 
46 using namespace lt;
47 
TORRENT_TEST(seed_mode)48 TORRENT_TEST(seed_mode)
49 {
50 	// with seed mode
51 	setup_swarm(2, swarm_test::upload
52 		// add session
53 		, [](lt::settings_pack& pack) {
54 			// make sure the session works with a tick interval of 5 seconds
55 			pack.set_int(settings_pack::tick_interval, 5000);
56 		}
57 		// add torrent
58 		, [](lt::add_torrent_params& params) {
59 			params.flags |= torrent_flags::seed_mode;
60 		}
61 		// on alert
62 		, [](lt::alert const*, lt::session&) {}
63 		// terminate
64 		, [](int ticks, lt::session&) -> bool {
65 			// we don't need to finish seeding, exit after 20 seconds
66 			return ticks > 20;
67 		});
68 }
69 
70 #ifndef TORRENT_DISABLE_LOGGING
TORRENT_TEST(ip_notifier_setting)71 TORRENT_TEST(ip_notifier_setting)
72 {
73 	int s_tick = 0;
74 	int working_count = 0;
75 
76 	setup_swarm(1, swarm_test::upload
77 		// add session
78 		, [](lt::settings_pack& pack)
79 		{
80 			pack.set_int(settings_pack::tick_interval, 1000);
81 			pack.set_int(settings_pack::alert_mask, alert_category::all);
82 		}
83 		// add torrent
84 		, [](lt::add_torrent_params&) {}
85 		// on alert
86 		, [&s_tick, &working_count](lt::alert const* a, lt::session&)
87 		{
88 			std::string const msg = a->message();
89 			if (msg.find("received error on_ip_change:") != std::string::npos)
90 			{
91 				TEST_CHECK(s_tick == 0 || s_tick == 2);
92 				working_count++;
93 			}
94 		}
95 		// terminate
96 		, [&s_tick](int ticks, lt::session& ses) -> bool {
97 
98 			if (ticks == 1)
99 			{
100 				settings_pack sp;
101 				sp.set_bool(settings_pack::enable_ip_notifier, false);
102 				ses.apply_settings(sp);
103 			}
104 			else if (ticks == 2)
105 			{
106 				settings_pack sp;
107 				sp.set_bool(settings_pack::enable_ip_notifier, true);
108 				ses.apply_settings(sp);
109 			}
110 
111 			s_tick = ticks;
112 
113 			// exit after 3 seconds
114 			return ticks > 3;
115 		});
116 
117 	TEST_EQUAL(working_count, 2);
118 }
119 #endif
120 
121 #ifndef TORRENT_DISABLE_EXTENSIONS
122 struct test_plugin : lt::torrent_plugin
123 {
124 	bool m_new_connection = false;
125 	bool m_files_checked = false;
126 
new_connectiontest_plugin127 	std::shared_ptr<peer_plugin> new_connection(peer_connection_handle const&) override
128 	{
129 		m_new_connection = true;
130 		return std::shared_ptr<peer_plugin>();
131 	}
132 
on_files_checkedtest_plugin133 	void on_files_checked() override
134 	{
135 		m_files_checked = true;
136 	}
137 };
138 
TORRENT_TEST(add_extension_while_transfer)139 TORRENT_TEST(add_extension_while_transfer)
140 {
141 	bool done = false;
142 	auto p = std::make_shared<test_plugin>();
143 
144 	setup_swarm(2, swarm_test::download
145 		// add session
146 		, [](lt::settings_pack& pack)
147 		{
148 			pack.set_int(settings_pack::tick_interval, 1000);
149 			pack.set_int(settings_pack::alert_mask, alert_category::all);
150 		}
151 		// add torrent
152 		, [](lt::add_torrent_params&) {}
153 		// on alert
154 		, [&done, p](lt::alert const* a, lt::session&)
155 		{
156 			if (a->type() == peer_connect_alert::alert_type)
157 			{
158 				auto create_test_plugin = [p](torrent_handle const&, void*)
159 				{ return p; };
160 
161 				lt::torrent_handle th = alert_cast<peer_connect_alert>(a)->handle;
162 				th.add_extension(create_test_plugin);
163 
164 				done = true;
165 			}
166 		}
167 		// terminate
168 		, [&done](int ticks, lt::session&) -> bool
169 		{
170 			// exit after 10 seconds
171 			return ticks > 10 || done;
172 		});
173 
174 	TEST_CHECK(done);
175 	TEST_CHECK(p->m_new_connection);
176 	TEST_CHECK(p->m_files_checked);
177 }
178 #endif // TORRENT_DISABLE_EXTENSIONS
179 
180 // make sure TCP and UDP listen sockets use the same port
TORRENT_TEST(tie_listen_ports)181 TORRENT_TEST(tie_listen_ports)
182 {
183 	using namespace libtorrent;
184 
185 	sim::default_config network_cfg;
186 	sim::simulation sim{network_cfg};
187 	sim::asio::io_service ios { sim, addr("50.0.0.1")};
188 
189 	lt::session_proxy zombie;
190 
191 	// create session
192 	auto pack = settings();
193 	pack.set_str(settings_pack::listen_interfaces, "0.0.0.0:0");
194 	pack.set_int(settings_pack::alert_mask, alert_category::error
195 		| alert_category::status
196 		| alert_category::torrent_log);
197 
198 	auto ses = std::make_shared<lt::session>(pack, ios);
199 
200 	std::vector<int> listen_ports;
201 
202 	// only monitor alerts for session 0 (the downloader)
203 	print_alerts(*ses, [&](lt::session&, lt::alert const* a){
204 		if (auto const* la = alert_cast<listen_succeeded_alert>(a))
205 		{
206 			listen_ports.push_back(la->port);
207 		}
208 	});
209 
210 	sim::timer t(sim, lt::seconds(30), [&](boost::system::error_code const&)
211 	{
212 	// TEST
213 		zombie = ses->abort();
214 		ses.reset();
215 
216 		TEST_CHECK(listen_ports.size() > 0);
217 		int const port = listen_ports.front();
218 		for (int const p : listen_ports)
219 			TEST_EQUAL(p, port);
220 	});
221 
222 	sim.run();
223 }
224 
225 // make sure passing in the session::paused flag does indeed start the session
226 // paused
TORRENT_TEST(construct_paused_session)227 TORRENT_TEST(construct_paused_session)
228 {
229 	using namespace libtorrent;
230 
231 	sim::default_config network_cfg;
232 	sim::simulation sim{network_cfg};
233 	sim::asio::io_service ios { sim, addr("50.0.0.1")};
234 
235 	lt::session_proxy zombie;
236 
237 	// create session
238 	auto pack = settings();
239 	pack.set_str(settings_pack::listen_interfaces, "0.0.0.0:0");
240 	pack.set_int(settings_pack::alert_mask, alert_category::error
241 		| alert_category::status
242 		| alert_category::torrent_log);
243 
244 	auto ses = std::make_shared<lt::session>(pack, ios, session::paused);
245 
246 	sim::timer t(sim, lt::seconds(30), [&](boost::system::error_code const&)
247 	{
248 		TEST_CHECK(ses->is_paused());
249 		zombie = ses->abort();
250 		ses.reset();
251 	});
252 
253 	sim.run();
254 }
255