fixed typo
[libtorrent.git] / test / test_fast_extension.cpp
blob2a5166c63f0e12c240b380eab5061bdab45b0a7b
1 /*
3 Copyright (c) 2008, Arvid Norberg
4 All rights reserved.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
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 "test.hpp"
34 #include "setup_transfer.hpp"
35 #include "libtorrent/socket.hpp"
36 #include "libtorrent/io.hpp"
37 #include <cstring>
38 #include <boost/bind.hpp>
40 using namespace libtorrent;
42 int read_message(stream_socket& s, char* buffer)
44 using namespace libtorrent::detail;
45 error_code ec;
46 libtorrent::asio::read(s, libtorrent::asio::buffer(buffer, 4), libtorrent::asio::transfer_all(), ec);
47 if (ec)
49 std::cout << ec.message() << std::endl;
50 exit(1);
52 char* ptr = buffer;
53 int length = read_int32(ptr);
55 libtorrent::asio::read(s, libtorrent::asio::buffer(buffer, length), libtorrent::asio::transfer_all(), ec);
56 if (ec)
58 std::cout << ec.message() << std::endl;
59 exit(1);
61 return length;
64 char const* message_name[] = {"choke", "unchoke", "interested", "not_interested"
65 , "have", "bitfield", "request", "piece", "cancel", "dht_port", "", "", ""
66 , "suggest_piece", "have_all", "have_none", "reject_request", "allowed_fast"};
68 void send_allow_fast(stream_socket& s, int piece)
70 std::cout << "send allow fast: " << piece << std::endl;
71 using namespace libtorrent::detail;
72 char msg[] = "\0\0\0\x05\x11\0\0\0\0";
73 char* ptr = msg + 5;
74 write_int32(piece, ptr);
75 error_code ec;
76 libtorrent::asio::write(s, libtorrent::asio::buffer(msg, 9), libtorrent::asio::transfer_all(), ec);
77 if (ec)
79 std::cout << ec.message() << std::endl;
80 exit(1);
84 void send_suggest_piece(stream_socket& s, int piece)
86 std::cout << "send suggest piece: " << piece << std::endl;
87 using namespace libtorrent::detail;
88 char msg[] = "\0\0\0\x05\x0d\0\0\0\0";
89 char* ptr = msg + 5;
90 write_int32(piece, ptr);
91 error_code ec;
92 libtorrent::asio::write(s, libtorrent::asio::buffer(msg, 9), libtorrent::asio::transfer_all(), ec);
93 if (ec)
95 std::cout << ec.message() << std::endl;
96 exit(1);
100 void send_unchoke(stream_socket& s)
102 std::cout << "send unchoke" << std::endl;
103 char msg[] = "\0\0\0\x01\x01";
104 error_code ec;
105 libtorrent::asio::write(s, libtorrent::asio::buffer(msg, 5), libtorrent::asio::transfer_all(), ec);
106 if (ec)
108 std::cout << ec.message() << std::endl;
109 exit(1);
113 void do_handshake(stream_socket& s, sha1_hash const& ih, char* buffer)
115 char handshake[] = "\x13" "BitTorrent protocol\0\0\0\0\0\0\0\x04"
116 " " // space for info-hash
117 "aaaaaaaaaaaaaaaaaaaa" // peer-id
118 "\0\0\0\x01\x0e"; // have_all
119 std::cout << "send handshake" << std::endl;
120 error_code ec;
121 std::memcpy(handshake + 28, ih.begin(), 20);
122 libtorrent::asio::write(s, libtorrent::asio::buffer(handshake, sizeof(handshake) - 1), libtorrent::asio::transfer_all(), ec);
123 if (ec)
125 std::cout << ec.message() << std::endl;
126 exit(1);
129 // read handshake
130 libtorrent::asio::read(s, libtorrent::asio::buffer(buffer, 68), libtorrent::asio::transfer_all(), ec);
131 if (ec)
133 std::cout << ec.message() << std::endl;
134 exit(1);
136 std::cout << "received handshake" << std::endl;
138 TEST_CHECK(buffer[0] == 19);
139 TEST_CHECK(std::memcmp(buffer + 1, "BitTorrent protocol", 19) == 0);
141 char* extensions = buffer + 20;
142 // check for fast extension support
143 TEST_CHECK(extensions[7] & 0x4);
145 #ifndef TORRENT_DISABLE_EXTENSIONS
146 // check for extension protocol support
147 TEST_CHECK(extensions[5] & 0x10);
148 #endif
150 #ifndef TORRENT_DISABLE_DHT
151 // check for DHT support
152 TEST_CHECK(extensions[7] & 0x1);
153 #endif
155 TEST_CHECK(std::memcmp(buffer + 28, ih.begin(), 20) == 0);
158 // makes sure that pieces that are allowed and then
159 // rejected aren't requested again
160 void test_reject_fast()
162 boost::intrusive_ptr<torrent_info> t = ::create_torrent();
163 sha1_hash ih = t->info_hash();
164 session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48900, 49000));
165 ses1.add_torrent(t, "./tmp1");
167 test_sleep(2000);
169 io_service ios;
170 stream_socket s(ios);
171 s.connect(tcp::endpoint(address::from_string("127.0.0.1"), ses1.listen_port()));
173 char recv_buffer[1000];
174 do_handshake(s, ih, recv_buffer);
176 std::vector<int> allowed_fast;
177 allowed_fast.push_back(0);
178 allowed_fast.push_back(1);
179 allowed_fast.push_back(2);
180 allowed_fast.push_back(3);
182 std::for_each(allowed_fast.begin(), allowed_fast.end()
183 , bind(&send_allow_fast, boost::ref(s), _1));
185 while (!allowed_fast.empty())
187 read_message(s, recv_buffer);
188 int msg = recv_buffer[0];
189 if (msg >= 0 && msg < int(sizeof(message_name)/sizeof(message_name[0])))
190 std::cerr << message_name[msg] << std::endl;
191 else
192 std::cerr << msg << std::endl;
193 if (recv_buffer[0] != 0x6) continue;
195 using namespace libtorrent::detail;
196 char* ptr = recv_buffer + 1;
197 int piece = read_int32(ptr);
199 std::vector<int>::iterator i = std::find(allowed_fast.begin()
200 , allowed_fast.end(), piece);
201 TEST_CHECK(i != allowed_fast.end());
202 if (i != allowed_fast.end())
203 allowed_fast.erase(i);
204 // send reject request
205 recv_buffer[0] = 0x10;
206 error_code ec;
207 libtorrent::asio::write(s, libtorrent::asio::buffer("\0\0\0\x0d", 4), libtorrent::asio::transfer_all(), ec);
208 if (ec)
210 std::cout << ec.message() << std::endl;
211 exit(1);
213 libtorrent::asio::write(s, libtorrent::asio::buffer(recv_buffer, 13), libtorrent::asio::transfer_all(), ec);
214 std::cout << ec.message() << std::endl;
215 if (ec)
217 std::cout << ec.message() << std::endl;
218 exit(1);
223 void test_respect_suggest()
225 boost::intrusive_ptr<torrent_info> t = ::create_torrent();
226 sha1_hash ih = t->info_hash();
227 session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48900, 49000));
228 ses1.add_torrent(t, "./tmp1");
230 test_sleep(2000);
232 io_service ios;
233 stream_socket s(ios);
234 s.connect(tcp::endpoint(address::from_string("127.0.0.1"), ses1.listen_port()));
236 char recv_buffer[1000];
237 do_handshake(s, ih, recv_buffer);
239 std::vector<int> suggested;
240 suggested.push_back(0);
241 suggested.push_back(1);
242 suggested.push_back(2);
243 suggested.push_back(3);
245 std::for_each(suggested.begin(), suggested.end()
246 , bind(&send_suggest_piece, boost::ref(s), _1));
248 send_unchoke(s);
250 int fail_counter = 100;
251 while (!suggested.empty() && fail_counter > 0)
253 read_message(s, recv_buffer);
254 std::cerr << "msg: ";
255 int msg = recv_buffer[0];
256 if (msg >= 0 && msg < int(sizeof(message_name)/sizeof(message_name[0])))
257 std::cerr << message_name[msg] << std::endl;
258 else
259 std::cerr << msg << std::endl;
260 fail_counter--;
261 if (recv_buffer[0] != 0x6) continue;
263 using namespace libtorrent::detail;
264 char* ptr = recv_buffer + 1;
265 int piece = read_int32(ptr);
267 std::vector<int>::iterator i = std::find(suggested.begin()
268 , suggested.end(), piece);
269 TEST_CHECK(i != suggested.end());
270 if (i != suggested.end())
271 suggested.erase(i);
272 // send reject request
273 recv_buffer[0] = 0x10;
274 error_code ec;
275 libtorrent::asio::write(s, libtorrent::asio::buffer("\0\0\0\x0d", 4), libtorrent::asio::transfer_all(), ec);
276 if (ec)
278 std::cout << ec.message() << std::endl;
279 exit(1);
281 libtorrent::asio::write(s, libtorrent::asio::buffer(recv_buffer, 13), libtorrent::asio::transfer_all(), ec);
282 if (ec)
284 std::cout << ec.message() << std::endl;
285 exit(1);
288 TEST_CHECK(fail_counter > 0);
291 int test_main()
293 test_reject_fast();
294 test_respect_suggest();
295 return 0;