merged changes from RC_1_0

This commit is contained in:
Arvid Norberg 2014-08-27 05:57:37 +00:00
parent 1ce69d122b
commit 48ea42c990
11 changed files with 314 additions and 127 deletions

View File

@ -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

118
bindings/python/setup.py Normal file
View File

@ -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
)

View File

@ -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>
{
&quot;a&quot;:
{
&quot;cas&quot;: <em>&lt;optional 20 byte hash (string)&gt;</em>,
&quot;cas&quot;: <em>&lt;optional expected seq-nr (int)&gt;</em>,
&quot;id&quot;: <em>&lt;20 byte id of sending node (string)&gt;</em>,
&quot;k&quot;: <em>&lt;ed25519 public key (32 bytes string)&gt;</em>,
&quot;salt&quot;: <em>&lt;optional salt to be appended to &quot;k&quot; when hashing (string)&gt;</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
&quot;y&quot;: &quot;r&quot;,
}
</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 &quot;y&quot; is &quot;e&quot; and &quot;e&quot; 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>

View File

@ -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.

View File

@ -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; }

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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()))

View File

@ -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();
}

View File

@ -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)