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