merged changes from RC_1_0
This commit is contained in:
parent
1ce69d122b
commit
48ea42c990
|
@ -27,6 +27,8 @@
|
|||
* almost completely changed the storage interface (for custom storage)
|
||||
* added support for hashing pieces in multiple threads
|
||||
|
||||
* support IPv6 multicast in local service discovery
|
||||
* simplify CAS function in DHT put
|
||||
* support IPv6 traffic class (via the TOS setting)
|
||||
* made uTP re-enter slow-start after time-out
|
||||
* fixed uTP upload performance issue
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from distutils import sysconfig
|
||||
from distutils.core import setup, Extension
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
import shutil
|
||||
import multiprocessing
|
||||
import subprocess
|
||||
|
||||
def parse_cmd(cmdline, prefix, keep_prefix = False):
|
||||
ret = []
|
||||
for token in cmdline.split():
|
||||
if token[:len(prefix)] == prefix:
|
||||
if keep_prefix:
|
||||
ret.append(token)
|
||||
else:
|
||||
ret.append(token[len(prefix):])
|
||||
return ret
|
||||
|
||||
def arch():
|
||||
if platform.system() != 'Darwin': return []
|
||||
a = os.uname()[4]
|
||||
if a == 'Power Macintosh': a = 'ppc'
|
||||
return ['-arch', a]
|
||||
|
||||
def target_specific():
|
||||
|
||||
if platform.system() != 'Darwin': return []
|
||||
|
||||
# on mavericks, clang will fail when unknown arguments are
|
||||
# passed in. python distutils will pass in arguments it doesn't
|
||||
# know about
|
||||
return ['-Wno-error=unused-command-line-argument-hard-error-in-future']
|
||||
|
||||
try:
|
||||
with open('compile_flags') as _file:
|
||||
extra_cmd = _file.read()
|
||||
|
||||
except:
|
||||
extra_cmd = None
|
||||
|
||||
try:
|
||||
with open('link_flags') as _file:
|
||||
ldflags = _file.read()
|
||||
|
||||
except:
|
||||
ldflags = None
|
||||
|
||||
ext = None
|
||||
packages = None
|
||||
|
||||
if '--bjam' in sys.argv or ldflags == None or extra_cmd == None:
|
||||
|
||||
del sys.argv[sys.argv.index('--bjam')]
|
||||
|
||||
if not '--help' in sys.argv \
|
||||
and not '--help-commands' in sys.argv:
|
||||
|
||||
toolset = ''
|
||||
file_ext = '.so'
|
||||
|
||||
if platform.system() == 'Windows':
|
||||
# msvc 9.0 (2008) is the official windows compiler for python 2.6
|
||||
# http://docs.python.org/whatsnew/2.6.html#build-and-c-api-changes
|
||||
toolset = ' msvc-9.0'
|
||||
file_ext = '.pyd'
|
||||
|
||||
parallell_builds = ' -j%d' % multiprocessing.cpu_count()
|
||||
|
||||
# build libtorrent using bjam and build the installer with distutils
|
||||
cmdline = 'bjam boost=source link=static geoip=static boost-link=static release optimization=space stage_module --abbreviate-paths' + toolset + parallell_builds
|
||||
print(cmdline)
|
||||
if os.system(cmdline) != 0:
|
||||
print('build failed')
|
||||
sys.exit(1)
|
||||
|
||||
try: os.mkdir('build')
|
||||
except: pass
|
||||
try: shutil.rmtree('build/lib')
|
||||
except: pass
|
||||
try: os.mkdir('build/lib')
|
||||
except: pass
|
||||
try: os.mkdir('libtorrent')
|
||||
except: pass
|
||||
shutil.copyfile('libtorrent' + file_ext, 'build/lib/libtorrent' + file_ext)
|
||||
|
||||
packages = ['libtorrent']
|
||||
|
||||
else:
|
||||
|
||||
source_list = os.listdir(os.path.join(os.path.dirname(__file__), "src"))
|
||||
source_list = [os.path.join("src", s) for s in source_list if s.endswith(".cpp")]
|
||||
|
||||
ext = [Extension('libtorrent',
|
||||
sources = source_list,
|
||||
language='c++',
|
||||
include_dirs = ['../../../include'] + parse_cmd(extra_cmd, '-I'),
|
||||
library_dirs = ['../../src/.libs'] + parse_cmd(extra_cmd, '-L'),
|
||||
extra_link_args = ldflags.split() + arch(),
|
||||
extra_compile_args = parse_cmd(extra_cmd, '-D', True) + arch() \
|
||||
+ target_specific(),
|
||||
libraries = ['torrent-rasterbar'] + parse_cmd(extra_cmd, '-l'))]
|
||||
|
||||
setup(name = 'python-libtorrent',
|
||||
version = '1.0.1',
|
||||
author = 'Arvid Norberg',
|
||||
author_email = 'arvid@rasterbar.com',
|
||||
description = 'Python bindings for libtorrent-rasterbar',
|
||||
long_description = 'Python bindings for libtorrent-rasterbar',
|
||||
url = 'http://libtorrent.org',
|
||||
platforms = [platform.system() + '-' + platform.machine()],
|
||||
license = 'BSD',
|
||||
packages = packages,
|
||||
ext_modules = ext
|
||||
)
|
||||
|
|
@ -57,18 +57,21 @@
|
|||
</li>
|
||||
<li><a class="reference internal" href="#mutable-items" id="id8">mutable items</a><ul>
|
||||
<li><a class="reference internal" href="#id1" id="id9">put message</a></li>
|
||||
<li><a class="reference internal" href="#id2" id="id10">get message</a></li>
|
||||
<li><a class="reference internal" href="#cas" id="id10">CAS</a></li>
|
||||
<li><a class="reference internal" href="#response" id="id11">response</a></li>
|
||||
<li><a class="reference internal" href="#errors" id="id12">errors</a></li>
|
||||
<li><a class="reference internal" href="#id2" id="id13">get message</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#signature-verification" id="id11">signature verification</a></li>
|
||||
<li><a class="reference internal" href="#expiration" id="id12">expiration</a></li>
|
||||
<li><a class="reference internal" href="#test-vectors" id="id13">test vectors</a><ul>
|
||||
<li><a class="reference internal" href="#test-1-mutable" id="id14">test 1 (mutable)</a></li>
|
||||
<li><a class="reference internal" href="#test-2-mutable-with-salt" id="id15">test 2 (mutable with salt)</a></li>
|
||||
<li><a class="reference internal" href="#test-3-immutable" id="id16">test 3 (immutable)</a></li>
|
||||
<li><a class="reference internal" href="#signature-verification" id="id14">signature verification</a></li>
|
||||
<li><a class="reference internal" href="#expiration" id="id15">expiration</a></li>
|
||||
<li><a class="reference internal" href="#test-vectors" id="id16">test vectors</a><ul>
|
||||
<li><a class="reference internal" href="#test-1-mutable" id="id17">test 1 (mutable)</a></li>
|
||||
<li><a class="reference internal" href="#test-2-mutable-with-salt" id="id18">test 2 (mutable with salt)</a></li>
|
||||
<li><a class="reference internal" href="#test-3-immutable" id="id19">test 3 (immutable)</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#resources" id="id17">resources</a></li>
|
||||
<li><a class="reference internal" href="#resources" id="id20">resources</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>This is a proposal for an extension to the BitTorrent DHT to allow
|
||||
|
@ -220,7 +223,7 @@ the buffer to be signed is:</p>
|
|||
{
|
||||
"a":
|
||||
{
|
||||
"cas": <em><optional 20 byte hash (string)></em>,
|
||||
"cas": <em><optional expected seq-nr (int)></em>,
|
||||
"id": <em><20 byte id of sending node (string)></em>,
|
||||
"k": <em><ed25519 public key (32 bytes string)></em>,
|
||||
"salt": <em><optional salt to be appended to "k" when hashing (string)></em>
|
||||
|
@ -262,15 +265,25 @@ is intentional. When issuing a <tt class="docutils literal">get</tt> request for
|
|||
know what the salt is (because it is part of what the target ID that is being
|
||||
looked up is derived from). There is no need to repeat it back for bystanders
|
||||
to see.</p>
|
||||
<p>The <tt class="docutils literal">cas</tt> field is optional. If present it is interpreted as the sha-1 hash of
|
||||
the sequence number, <tt class="docutils literal">v</tt> field and possibly the <tt class="docutils literal">salt</tt> field, that is
|
||||
expected to be replaced. The buffer to hash is the same as the one signed when
|
||||
storing. <tt class="docutils literal">cas</tt> is short for <em>compare and swap</em>, it has similar semantics as
|
||||
CAS CPU instructions. If specified as part of the put command, and the current
|
||||
value stored under the public key differs from the expected value, the store
|
||||
fails. The <tt class="docutils literal">cas</tt> field only applies to mutable puts. If there is no current
|
||||
value, the <tt class="docutils literal">cas</tt> field SHOULD be ignored. A put operation should not be
|
||||
prevented based on the <tt class="docutils literal">cas</tt> field if no value is currently present.</p>
|
||||
</div>
|
||||
<div class="section" id="cas">
|
||||
<h2>CAS</h2>
|
||||
<p>CAS is short for <em>compare and swap</em>, it has similar semantics as CAS CPU
|
||||
instructions. It is used to avoid race conditions when multiple nodes are
|
||||
writing to the same slot in the DHT.</p>
|
||||
<p>The <tt class="docutils literal">cas</tt> field is optional. If present it specifies the sequence number of
|
||||
the data blob being overwritten by the put. When present, the storing node
|
||||
MUST compare this number to the current sequence number it has stored under
|
||||
this key. Only if the <tt class="docutils literal">cas</tt> matches the stored sequence number is the put
|
||||
performed. If it mismatches, the store fails and an error is returned.
|
||||
See <a class="reference internal" href="#errors">errors</a> below.</p>
|
||||
<p>The <tt class="docutils literal">cas</tt> field only applies to mutable puts. If there is no current
|
||||
value, the <tt class="docutils literal">cas</tt> field SHOULD be ignored.</p>
|
||||
<p>When sending a <tt class="docutils literal">put</tt> request to a node that did not return any data for the
|
||||
<tt class="docutils literal">get</tt>, the <tt class="docutils literal">cas</tt> field SHOULD NOT be included.</p>
|
||||
</div>
|
||||
<div class="section" id="response">
|
||||
<h2>response</h2>
|
||||
<p>Response:</p>
|
||||
<pre class="literal-block">
|
||||
{
|
||||
|
@ -279,13 +292,13 @@ prevented based on the <tt class="docutils literal">cas</tt> field if no value i
|
|||
"y": "r",
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section" id="errors">
|
||||
<h2>errors</h2>
|
||||
<p>If the store fails for any reason an error message is returned instead of the
|
||||
message template above, i.e. one where "y" is "e" and "e" is a tuple of
|
||||
[error-code, message]). Failures include where the <tt class="docutils literal">cas</tt> hash mismatches and
|
||||
the sequence number is outdated.</p>
|
||||
<p>If no <tt class="docutils literal">cas</tt> field is included in the <tt class="docutils literal">put</tt> message, the value of the current
|
||||
<tt class="docutils literal">v</tt> field should be disregarded when determining whether or not to save the
|
||||
item. (However, the signature, sequence number obviously still should).</p>
|
||||
[error-code, message]). Failures include <tt class="docutils literal">cas</tt> mismatches and the sequence
|
||||
number is outdated.</p>
|
||||
<p>The error message (as specified by <a class="reference external" href="http://www.bittorrent.org/beps/bep_0005.html">BEP5</a>) looks like this:</p>
|
||||
<pre class="literal-block">
|
||||
{
|
||||
|
@ -329,7 +342,7 @@ current.</td>
|
|||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>An implementation MUST emit 301 errors if the cas-hash mismatches. This is a
|
||||
<p>An implementation MUST emit 301 errors if the cas mismatches. This is a
|
||||
critical feature in synchronization of multiple agents sharing an immutable
|
||||
item.</p>
|
||||
</div>
|
||||
|
|
|
@ -189,7 +189,7 @@ Request:
|
|||
{
|
||||
"a":
|
||||
{
|
||||
"cas": *<optional 20 byte hash (string)>*,
|
||||
"cas": *<optional expected seq-nr (int)>*,
|
||||
"id": *<20 byte id of sending node (string)>*,
|
||||
"k": *<ed25519 public key (32 bytes string)>*,
|
||||
"salt": *<optional salt to be appended to "k" when hashing (string)>*
|
||||
|
@ -237,15 +237,28 @@ know what the salt is (because it is part of what the target ID that is being
|
|||
looked up is derived from). There is no need to repeat it back for bystanders
|
||||
to see.
|
||||
|
||||
The ``cas`` field is optional. If present it is interpreted as the sha-1 hash of
|
||||
the sequence number, ``v`` field and possibly the ``salt`` field, that is
|
||||
expected to be replaced. The buffer to hash is the same as the one signed when
|
||||
storing. ``cas`` is short for *compare and swap*, it has similar semantics as
|
||||
CAS CPU instructions. If specified as part of the put command, and the current
|
||||
value stored under the public key differs from the expected value, the store
|
||||
fails. The ``cas`` field only applies to mutable puts. If there is no current
|
||||
value, the ``cas`` field SHOULD be ignored. A put operation should not be
|
||||
prevented based on the ``cas`` field if no value is currently present.
|
||||
CAS
|
||||
...
|
||||
|
||||
CAS is short for *compare and swap*, it has similar semantics as CAS CPU
|
||||
instructions. It is used to avoid race conditions when multiple nodes are
|
||||
writing to the same slot in the DHT.
|
||||
|
||||
The ``cas`` field is optional. If present it specifies the sequence number of
|
||||
the data blob being overwritten by the put. When present, the storing node
|
||||
MUST compare this number to the current sequence number it has stored under
|
||||
this key. Only if the ``cas`` matches the stored sequence number is the put
|
||||
performed. If it mismatches, the store fails and an error is returned.
|
||||
See errors_ below.
|
||||
|
||||
The ``cas`` field only applies to mutable puts. If there is no current
|
||||
value, the ``cas`` field SHOULD be ignored.
|
||||
|
||||
When sending a ``put`` request to a node that did not return any data for the
|
||||
``get``, the ``cas`` field SHOULD NOT be included.
|
||||
|
||||
response
|
||||
........
|
||||
|
||||
Response:
|
||||
|
||||
|
@ -257,14 +270,13 @@ Response:
|
|||
"y": "r",
|
||||
}
|
||||
|
||||
errors
|
||||
......
|
||||
|
||||
If the store fails for any reason an error message is returned instead of the
|
||||
message template above, i.e. one where "y" is "e" and "e" is a tuple of
|
||||
[error-code, message]). Failures include where the ``cas`` hash mismatches and
|
||||
the sequence number is outdated.
|
||||
|
||||
If no ``cas`` field is included in the ``put`` message, the value of the current
|
||||
``v`` field should be disregarded when determining whether or not to save the
|
||||
item. (However, the signature, sequence number obviously still should).
|
||||
[error-code, message]). Failures include ``cas`` mismatches and the sequence
|
||||
number is outdated.
|
||||
|
||||
The error message (as specified by BEP5_) looks like this:
|
||||
|
||||
|
@ -300,7 +312,7 @@ some additional error codes.
|
|||
| | current. |
|
||||
+------------+-----------------------------+
|
||||
|
||||
An implementation MUST emit 301 errors if the cas-hash mismatches. This is a
|
||||
An implementation MUST emit 301 errors if the cas mismatches. This is a
|
||||
critical feature in synchronization of multiple agents sharing an immutable
|
||||
item.
|
||||
|
||||
|
|
|
@ -75,11 +75,6 @@ void TORRENT_EXPORT sign_mutable_item(
|
|||
, char const* sk
|
||||
, char* sig);
|
||||
|
||||
sha1_hash TORRENT_EXTRA_EXPORT mutable_item_cas(
|
||||
std::pair<char const*, int> v
|
||||
, std::pair<char const*, int> salt
|
||||
, boost::uint64_t seq);
|
||||
|
||||
enum
|
||||
{
|
||||
item_pk_len = 32,
|
||||
|
@ -120,8 +115,6 @@ public:
|
|||
|
||||
bool is_mutable() const { return m_mutable; }
|
||||
|
||||
sha1_hash cas();
|
||||
|
||||
entry const& value() const { return m_value; }
|
||||
boost::array<char, item_pk_len> const& pk() const
|
||||
{ return m_pk; }
|
||||
|
|
|
@ -65,24 +65,26 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
void resend_announce(error_code const& e, std::string msg);
|
||||
void announce_impl(sha1_hash const& ih, int listen_port
|
||||
, bool broadcast, int retry_count);
|
||||
void resend_announce(error_code const& e, sha1_hash const& ih
|
||||
, int listen_port, int retry_count);
|
||||
void on_announce(udp::endpoint const& from, char* buffer
|
||||
, std::size_t bytes_transferred);
|
||||
// void setup_receive();
|
||||
|
||||
peer_callback_t m_callback;
|
||||
|
||||
// the udp socket used to send and receive
|
||||
// multicast messages on
|
||||
broadcast_socket m_socket;
|
||||
#if TORRENT_USE_IPV6
|
||||
broadcast_socket m_socket6;
|
||||
#endif
|
||||
|
||||
// used to resend udp packets in case
|
||||
// they time out
|
||||
deadline_timer m_broadcast_timer;
|
||||
|
||||
// current retry count
|
||||
boost::uint32_t m_retry_count;
|
||||
|
||||
// this is a random (presumably unique)
|
||||
// ID for this LSD node. It is used to
|
||||
// ignore our own broadcast messages.
|
||||
|
@ -91,6 +93,9 @@ private:
|
|||
int m_cookie;
|
||||
|
||||
bool m_disabled;
|
||||
#if TORRENT_USE_IPV6
|
||||
bool m_disabled6;
|
||||
#endif
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
FILE* m_log;
|
||||
#endif
|
||||
|
|
|
@ -209,7 +209,7 @@ namespace libtorrent
|
|||
- common_bits(b1.data(), b2.data(), b1.size());
|
||||
#if TORRENT_USE_IPV6
|
||||
}
|
||||
|
||||
|
||||
address_v6::bytes_type b1;
|
||||
address_v6::bytes_type b2;
|
||||
if (a1.is_v4()) b1 = address_v6::v4_mapped(a1.to_v4()).to_bytes();
|
||||
|
@ -244,7 +244,7 @@ namespace libtorrent
|
|||
else
|
||||
#endif
|
||||
open_multicast_socket(ios, address_v4::any(), loopback, ec);
|
||||
|
||||
|
||||
for (std::vector<ip_interface>::const_iterator i = interfaces.begin()
|
||||
, end(interfaces.end()); i != end; ++i)
|
||||
{
|
||||
|
@ -254,6 +254,19 @@ namespace libtorrent
|
|||
if (!loopback && is_loopback(i->interface_address)) continue;
|
||||
|
||||
ec = error_code();
|
||||
#if TORRENT_USE_IPV6
|
||||
if (i->interface_address.is_v6() &&
|
||||
i->interface_address.to_v6().is_link_local()) {
|
||||
address_v6 addr6 = i->interface_address.to_v6();
|
||||
addr6.scope_id(if_nametoindex(i->name));
|
||||
open_multicast_socket(ios, addr6, loopback, ec);
|
||||
|
||||
address_v4 const& mask = i->netmask.is_v4() ?
|
||||
i->netmask.to_v4() : address_v4();
|
||||
open_unicast_socket(ios, addr6, mask);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
open_multicast_socket(ios, i->interface_address, loopback, ec);
|
||||
#ifdef TORRENT_DEBUG
|
||||
// fprintf(stderr, "broadcast socket [ if: %s group: %s mask: %s ] %s\n"
|
||||
|
|
|
@ -150,15 +150,6 @@ void sign_mutable_item(
|
|||
);
|
||||
}
|
||||
|
||||
sha1_hash mutable_item_cas(std::pair<char const*, int> v
|
||||
, std::pair<char const*, int> salt
|
||||
, boost::uint64_t seq)
|
||||
{
|
||||
char str[canonical_length];
|
||||
int len = canonical_string(v, seq, salt, str);
|
||||
return hasher(str, len).final();
|
||||
}
|
||||
|
||||
item::item(char const* pk, std::string const& salt)
|
||||
: m_salt(salt)
|
||||
, m_seq(0)
|
||||
|
@ -230,12 +221,4 @@ void item::assign(entry const& v, std::string salt, boost::uint64_t seq
|
|||
m_value = v;
|
||||
}
|
||||
|
||||
sha1_hash item::cas()
|
||||
{
|
||||
char buffer[1000];
|
||||
int bsize = bencode(buffer, m_value);
|
||||
return mutable_item_cas(std::make_pair(buffer, bsize)
|
||||
, std::pair<char const*, int>(m_salt.c_str(), m_salt.size()), m_seq);
|
||||
}
|
||||
|
||||
} } // namespace libtorrent::dht
|
||||
|
|
|
@ -952,7 +952,7 @@ void node_impl::incoming_request(msg const& m, entry& e)
|
|||
// public key
|
||||
{"k", lazy_entry::string_t, item_pk_len, key_desc_t::optional},
|
||||
{"sig", lazy_entry::string_t, item_sig_len, key_desc_t::optional},
|
||||
{"cas", lazy_entry::string_t, 20, key_desc_t::optional},
|
||||
{"cas", lazy_entry::int_t, 0, key_desc_t::optional},
|
||||
{"salt", lazy_entry::string_t, 0, key_desc_t::optional},
|
||||
};
|
||||
|
||||
|
@ -1115,20 +1115,14 @@ void node_impl::incoming_request(msg const& m, entry& e)
|
|||
dht_mutable_item* item = &i->second;
|
||||
|
||||
// this is the "cas" field in the put message
|
||||
// if it was specified, we MUST make sure the current value
|
||||
// matches the expected value before replacing it
|
||||
if (msg_keys[5])
|
||||
// if it was specified, we MUST make sure the current sequence
|
||||
// number matches the expected value before replacing it
|
||||
// this is critical for avoiding race conditions when multiple
|
||||
// writers are accessing the same slot
|
||||
if (msg_keys[5] && item->seq != msg_keys[5]->int_value())
|
||||
{
|
||||
sha1_hash h = mutable_item_cas(
|
||||
std::make_pair(item->value, item->size)
|
||||
, std::make_pair(item->salt, item->salt_size)
|
||||
, item->seq);
|
||||
|
||||
if (h != sha1_hash(msg_keys[5]->string_ptr()))
|
||||
{
|
||||
incoming_error(e, "CAS hash failed", 301);
|
||||
return;
|
||||
}
|
||||
incoming_error(e, "CAS mismatch", 301);
|
||||
return;
|
||||
}
|
||||
|
||||
if (item->seq > boost::uint64_t(msg_keys[2]->int_value()))
|
||||
|
|
119
src/lsd.cpp
119
src/lsd.cpp
|
@ -69,10 +69,16 @@ lsd::lsd(io_service& ios, peer_callback_t const& cb)
|
|||
: m_callback(cb)
|
||||
, m_socket(udp::endpoint(address_v4::from_string("239.192.152.143", ec), 6771)
|
||||
, boost::bind(&lsd::on_announce, self(), _1, _2, _3))
|
||||
#if TORRENT_USE_IPV6
|
||||
, m_socket6(udp::endpoint(address_v6::from_string("ff15::efc0:988f", ec), 6771)
|
||||
, boost::bind(&lsd::on_announce, self(), _1, _2, _3))
|
||||
#endif
|
||||
, m_broadcast_timer(ios)
|
||||
, m_retry_count(1)
|
||||
, m_cookie(random())
|
||||
, m_disabled(false)
|
||||
#if TORRENT_USE_IPV6
|
||||
, m_disabled6(false)
|
||||
#endif
|
||||
{
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
m_log = fopen("lsd.log", "w+");
|
||||
|
@ -93,6 +99,17 @@ lsd::lsd(io_service& ios, peer_callback_t const& cb)
|
|||
, ec.value(), ec.message().c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TORRENT_USE_IPV6
|
||||
m_socket6.open(ios, ec);
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
if (ec)
|
||||
{
|
||||
if (m_log) fprintf(m_log, "FAILED TO OPEN SOCKET6: (%d) %s\n"
|
||||
, ec.value(), ec.message().c_str());
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
lsd::~lsd()
|
||||
|
@ -102,70 +119,100 @@ lsd::~lsd()
|
|||
#endif
|
||||
}
|
||||
|
||||
int render_lsd_packet(char* dst, int len, int listen_port
|
||||
, char const* info_hash_hex, int m_cookie, char const* host)
|
||||
{
|
||||
return snprintf(dst, len,
|
||||
"BT-SEARCH * HTTP/1.1\r\n"
|
||||
"Host: %s:6771\r\n"
|
||||
"Port: %d\r\n"
|
||||
"Infohash: %s\r\n"
|
||||
"cookie: %x\r\n"
|
||||
"\r\n\r\n", host, listen_port, info_hash_hex, m_cookie);
|
||||
}
|
||||
|
||||
void lsd::announce(sha1_hash const& ih, int listen_port, bool broadcast)
|
||||
{
|
||||
announce_impl(ih, listen_port, broadcast, 0);
|
||||
}
|
||||
|
||||
void lsd::announce_impl(sha1_hash const& ih, int listen_port, bool broadcast
|
||||
, int retry_count)
|
||||
{
|
||||
#if TORRENT_USE_IPV6
|
||||
if (m_disabled && m_disabled6) return;
|
||||
#else
|
||||
if (m_disabled) return;
|
||||
#endif
|
||||
|
||||
char ih_hex[41];
|
||||
to_hex((char const*)&ih[0], 20, ih_hex);
|
||||
char msg[200];
|
||||
int msg_len = snprintf(msg, sizeof(msg),
|
||||
"BT-SEARCH * HTTP/1.1\r\n"
|
||||
"Host: 239.192.152.143:6771\r\n"
|
||||
"Port: %d\r\n"
|
||||
"Infohash: %s\r\n"
|
||||
"cookie: %x\r\n"
|
||||
"\r\n\r\n", listen_port, ih_hex, m_cookie);
|
||||
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
{
|
||||
if (m_log) fprintf(m_log, "%s ==> announce: ih: %s port: %u\n"
|
||||
, time_now_string(), ih_hex, listen_port);
|
||||
}
|
||||
if (m_log) fprintf(m_log, "%s ==> announce: ih: %s port: %u\n"
|
||||
, time_now_string(), ih_hex, listen_port);
|
||||
#endif
|
||||
|
||||
m_retry_count = 1;
|
||||
error_code ec;
|
||||
m_socket.send(msg, msg_len, ec, broadcast ? broadcast_socket::broadcast : 0);
|
||||
if (ec)
|
||||
if (!m_disabled)
|
||||
{
|
||||
m_disabled = true;
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
int msg_len = render_lsd_packet(msg, sizeof(msg), listen_port, ih_hex
|
||||
, m_cookie, "239.192.152.143");
|
||||
m_socket.send(msg, msg_len, ec, broadcast ? broadcast_socket::broadcast : 0);
|
||||
if (ec)
|
||||
{
|
||||
m_disabled = true;
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
if (m_log) fprintf(m_log, "%s failed to send message: (%d) %s"
|
||||
, time_now_string(), ec.value(), ec.message().c_str());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if TORRENT_USE_IPV6
|
||||
if (!m_disabled6)
|
||||
{
|
||||
int msg_len = render_lsd_packet(msg, sizeof(msg), listen_port, ih_hex
|
||||
, m_cookie, "[ff15::efc0:988f]");
|
||||
m_socket6.send(msg, msg_len, ec, broadcast ? broadcast_socket::broadcast : 0);
|
||||
if (ec)
|
||||
{
|
||||
m_disabled6 = true;
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
if (m_log) fprintf(m_log, "%s failed to send message6: (%d) %s"
|
||||
, time_now_string(), ec.value(), ec.message().c_str());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
++retry_count;
|
||||
if (retry_count >= 3) return;
|
||||
|
||||
#if TORRENT_USE_IPV6
|
||||
if (m_disabled && m_disabled6) return;
|
||||
#else
|
||||
if (m_disabled) return;
|
||||
#endif
|
||||
|
||||
#if defined TORRENT_ASIO_DEBUGGING
|
||||
add_outstanding_async("lsd::resend_announce");
|
||||
#endif
|
||||
m_broadcast_timer.expires_from_now(seconds(2 * m_retry_count), ec);
|
||||
m_broadcast_timer.expires_from_now(seconds(2 * retry_count), ec);
|
||||
m_broadcast_timer.async_wait(boost::bind(&lsd::resend_announce, self(), _1
|
||||
, std::string(msg)));
|
||||
, ih, listen_port, retry_count));
|
||||
}
|
||||
|
||||
void lsd::resend_announce(error_code const& e, std::string msg)
|
||||
void lsd::resend_announce(error_code const& e, sha1_hash const& info_hash
|
||||
, int listen_port, int retry_count)
|
||||
{
|
||||
#if defined TORRENT_ASIO_DEBUGGING
|
||||
complete_async("lsd::resend_announce");
|
||||
#endif
|
||||
if (e) return;
|
||||
|
||||
error_code ec;
|
||||
m_socket.send(msg.c_str(), int(msg.size()), ec);
|
||||
|
||||
++m_retry_count;
|
||||
if (m_retry_count >= 3) return;
|
||||
|
||||
#if defined TORRENT_ASIO_DEBUGGING
|
||||
add_outstanding_async("lsd::resend_announce");
|
||||
#endif
|
||||
m_broadcast_timer.expires_from_now(seconds(2 * m_retry_count), ec);
|
||||
m_broadcast_timer.async_wait(boost::bind(&lsd::resend_announce, self(), _1, msg));
|
||||
announce_impl(info_hash, listen_port, false, retry_count);
|
||||
}
|
||||
|
||||
void lsd::on_announce(udp::endpoint const& from, char* buffer
|
||||
|
@ -263,9 +310,15 @@ void lsd::on_announce(udp::endpoint const& from, char* buffer
|
|||
void lsd::close()
|
||||
{
|
||||
m_socket.close();
|
||||
#if TORRENT_USE_IPV6
|
||||
m_socket6.close();
|
||||
#endif
|
||||
error_code ec;
|
||||
m_broadcast_timer.cancel(ec);
|
||||
m_disabled = true;
|
||||
#if TORRENT_USE_IPV6
|
||||
m_disabled6 = true;
|
||||
#endif
|
||||
m_callback.clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ void send_dht_request(node_impl& node, char const* msg, udp::endpoint const& ep
|
|||
, char const* target = 0, entry const* value = 0
|
||||
, bool scrape = false, bool seed = false
|
||||
, std::string const key = std::string(), std::string const sig = std::string()
|
||||
, int seq = -1, char const* cas = 0, sha1_hash const* nid = NULL
|
||||
, int seq = -1, boost::int64_t cas = -1, sha1_hash const* nid = NULL
|
||||
, char const* put_salt = NULL)
|
||||
{
|
||||
// we're about to clear out the backing buffer
|
||||
|
@ -164,7 +164,7 @@ void send_dht_request(node_impl& node, char const* msg, udp::endpoint const& ep
|
|||
if (scrape) a["scrape"] = 1;
|
||||
if (seed) a["seed"] = 1;
|
||||
if (seq >= 0) a["seq"] = seq;
|
||||
if (cas) a["cas"] = std::string(cas, 20);
|
||||
if (cas != -1) a["cas"] = cas;
|
||||
if (put_salt) a["salt"] = put_salt;
|
||||
char msg_buf[1500];
|
||||
int size = bencode(msg_buf, e);
|
||||
|
@ -832,7 +832,7 @@ int test_main()
|
|||
send_dht_request(node, "put", source, &response, "10", 0
|
||||
, 0, token, 0, 0, &items[0].ent, false, false
|
||||
, std::string(public_key, item_pk_len)
|
||||
, std::string(signature, item_sig_len), seq, NULL, NULL, salt.first);
|
||||
, std::string(signature, item_sig_len), seq, -1, NULL, salt.first);
|
||||
|
||||
ret = verify_message(&response, desc2, parsed, 1, error_string, sizeof(error_string));
|
||||
if (ret)
|
||||
|
@ -905,7 +905,7 @@ int test_main()
|
|||
send_dht_request(node, "put", source, &response, "10", 0
|
||||
, 0, token, 0, 0, &items[0].ent, false, false
|
||||
, std::string(public_key, item_pk_len)
|
||||
, std::string(signature, item_sig_len), seq, NULL, NULL, salt.first);
|
||||
, std::string(signature, item_sig_len), seq, -1, NULL, salt.first);
|
||||
|
||||
ret = verify_message(&response, desc_error, parsed, 2, error_string, sizeof(error_string));
|
||||
if (ret)
|
||||
|
@ -924,8 +924,9 @@ int test_main()
|
|||
|
||||
// === test CAS put ===
|
||||
|
||||
// this is the hash that we expect to be there
|
||||
sha1_hash cas = mutable_item_cas(itemv, salt, seq);
|
||||
// this is the sequence number we expect to be there
|
||||
boost::uint64_t cas = seq;
|
||||
|
||||
// increment sequence number
|
||||
++seq;
|
||||
// put item 1
|
||||
|
@ -944,7 +945,7 @@ int test_main()
|
|||
, 0, token, 0, 0, &items[1].ent, false, false
|
||||
, std::string(public_key, item_pk_len)
|
||||
, std::string(signature, item_sig_len), seq
|
||||
, (char const*)&cas[0], NULL, salt.first);
|
||||
, cas, NULL, salt.first);
|
||||
|
||||
ret = verify_message(&response, desc2, parsed, 1, error_string, sizeof(error_string));
|
||||
if (ret)
|
||||
|
@ -969,7 +970,7 @@ int test_main()
|
|||
, 0, token, 0, 0, &items[1].ent, false, false
|
||||
, std::string(public_key, item_pk_len)
|
||||
, std::string(signature, item_sig_len), seq
|
||||
, (char const*)&cas[0], NULL, salt.first);
|
||||
, cas, NULL, salt.first);
|
||||
|
||||
ret = verify_message(&response, desc_error, parsed, 2, error_string, sizeof(error_string));
|
||||
if (ret)
|
||||
|
|
Loading…
Reference in New Issue