3 Copyright (c) 2008, Arvid Norberg
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
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.
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.
33 #include "libtorrent/session.hpp"
34 #include "libtorrent/session_settings.hpp"
35 #include "libtorrent/hasher.hpp"
36 #include "libtorrent/alert_types.hpp"
37 #include <boost/thread.hpp>
38 #include <boost/tuple/tuple.hpp>
39 #include <boost/filesystem/operations.hpp>
42 #include "setup_transfer.hpp"
44 using boost::filesystem::remove_all
;
45 using boost::filesystem::exists
;
49 using namespace libtorrent
;
51 session
ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48000, 49000));
52 session
ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49000, 50000));
53 session
ses3(fingerprint("LT", 0, 1, 0, 0), std::make_pair(50000, 51000));
55 // this is to avoid everything finish from a single peer
56 // immediately. To make the swarm actually connect all
57 // three peers before finishing.
58 float rate_limit
= 100000;
59 ses1
.set_upload_rate_limit(int(rate_limit
));
60 ses2
.set_download_rate_limit(int(rate_limit
));
61 ses3
.set_download_rate_limit(int(rate_limit
));
62 ses2
.set_upload_rate_limit(int(rate_limit
/ 2));
63 ses3
.set_upload_rate_limit(int(rate_limit
/ 2));
65 session_settings settings
;
66 settings
.allow_multiple_connections_per_ip
= true;
67 settings
.ignore_limits_on_local_network
= false;
68 ses1
.set_settings(settings
);
69 ses2
.set_settings(settings
);
70 ses3
.set_settings(settings
);
72 #ifndef TORRENT_DISABLE_ENCRYPTION
74 pes
.out_enc_policy
= pe_settings::forced
;
75 pes
.in_enc_policy
= pe_settings::forced
;
76 ses1
.set_pe_settings(pes
);
77 ses2
.set_pe_settings(pes
);
78 ses3
.set_pe_settings(pes
);
85 // test using piece sizes smaller than 16kB
86 boost::tie(tor1
, tor2
, tor3
) = setup_transfer(&ses1
, &ses2
, &ses3
, true, false, true, "_swarm", 8 * 1024);
88 ses1
.set_alert_mask(alert::all_categories
& ~alert::progress_notification
);
89 ses2
.set_alert_mask(alert::all_categories
& ~alert::progress_notification
);
90 ses3
.set_alert_mask(alert::all_categories
& ~alert::progress_notification
);
92 float sum_dl_rate2
= 0.f
;
93 float sum_dl_rate3
= 0.f
;
94 int count_dl_rates2
= 0;
95 int count_dl_rates3
= 0;
97 for (int i
= 0; i
< 30; ++i
)
99 print_alerts(ses1
, "ses1");
100 print_alerts(ses2
, "ses2");
101 print_alerts(ses3
, "ses3");
103 torrent_status st1
= tor1
.status();
104 torrent_status st2
= tor2
.status();
105 torrent_status st3
= tor3
.status();
107 if (st2
.progress
< 1.f
&& st2
.progress
> 0.5f
)
109 sum_dl_rate2
+= st2
.download_payload_rate
;
112 if (st3
.progress
< 1.f
&& st3
.progress
> 0.5f
)
114 sum_dl_rate3
+= st3
.download_rate
;
119 << "\033[33m" << int(st1
.upload_payload_rate
/ 1000.f
) << "kB/s "
120 << st1
.num_peers
<< ": "
121 << "\033[32m" << int(st2
.download_payload_rate
/ 1000.f
) << "kB/s "
122 << "\033[31m" << int(st2
.upload_payload_rate
/ 1000.f
) << "kB/s "
123 << "\033[0m" << int(st2
.progress
* 100) << "% "
124 << st2
.num_peers
<< " - "
125 << "\033[32m" << int(st3
.download_payload_rate
/ 1000.f
) << "kB/s "
126 << "\033[31m" << int(st3
.upload_payload_rate
/ 1000.f
) << "kB/s "
127 << "\033[0m" << int(st3
.progress
* 100) << "% "
131 if (tor2
.is_seed() && tor3
.is_seed()) break;
135 TEST_CHECK(tor2
.is_seed());
136 TEST_CHECK(tor3
.is_seed());
138 float average2
= sum_dl_rate2
/ float(count_dl_rates2
);
139 float average3
= sum_dl_rate3
/ float(count_dl_rates3
);
141 std::cerr
<< average2
<< std::endl
;
142 std::cerr
<< "average rate: " << (average2
/ 1000.f
) << "kB/s - "
143 << (average3
/ 1000.f
) << "kB/s" << std::endl
;
145 TEST_CHECK(std::fabs(average2
- float(rate_limit
)) < rate_limit
/ 11.f
);
146 TEST_CHECK(std::fabs(average3
- float(rate_limit
)) < rate_limit
/ 11.f
);
147 if (tor2
.is_seed() && tor3
.is_seed()) std::cerr
<< "done\n";
149 // make sure the files are deleted
150 ses1
.remove_torrent(tor1
, session::delete_files
);
151 ses2
.remove_torrent(tor2
, session::delete_files
);
152 ses3
.remove_torrent(tor3
, session::delete_files
);
154 std::auto_ptr
<alert
> a
= ses1
.pop_alert();
155 ptime end
= time_now() + seconds(20);
156 while (a
.get() == 0 || dynamic_cast<torrent_deleted_alert
*>(a
.get()) == 0)
158 if (ses1
.wait_for_alert(end
- time_now()) == 0)
160 std::cerr
<< "wait_for_alert() expired" << std::endl
;
163 a
= ses1
.pop_alert();
165 std::cerr
<< a
->message() << std::endl
;
168 TEST_CHECK(dynamic_cast<torrent_deleted_alert
*>(a
.get()) != 0);
170 // there shouldn't be any alerts generated from now on
171 // make sure that the timer in wait_for_alert() works
172 // this should time out (ret == 0) and it should take
174 ptime start
= time_now();
176 while (ret
= ses1
.wait_for_alert(seconds(2)))
178 a
= ses1
.pop_alert();
179 std::cerr
<< ret
->message() << std::endl
;
182 TEST_CHECK(time_now() - start
< seconds(3));
183 TEST_CHECK(time_now() - start
>= seconds(2));
188 using namespace libtorrent
;
189 using namespace boost::filesystem
;
191 // in case the previous run was terminated
192 try { remove_all("./tmp1_swarm"); } catch (std::exception
&) {}
193 try { remove_all("./tmp2_swarm"); } catch (std::exception
&) {}
194 try { remove_all("./tmp3_swarm"); } catch (std::exception
&) {}
199 TEST_CHECK(!exists("./tmp1_swarm/temporary"));
200 TEST_CHECK(!exists("./tmp2_swarm/temporary"));
201 TEST_CHECK(!exists("./tmp3_swarm/temporary"));
203 remove_all("./tmp1_swarm");
204 remove_all("./tmp2_swarm");
205 remove_all("./tmp3_swarm");