From 48ea42c9903a92c60921e8ce1a132f3bd5b8b0ea Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Wed, 27 Aug 2014 05:57:37 +0000 Subject: [PATCH] merged changes from RC_1_0 --- ChangeLog | 2 + bindings/python/setup.py | 118 ++++++++++++++++++++++++++ docs/dht_store.html | 61 ++++++++------ docs/dht_store.rst | 46 +++++++---- include/libtorrent/kademlia/item.hpp | 7 -- include/libtorrent/lsd.hpp | 15 ++-- src/broadcast_socket.cpp | 17 +++- src/kademlia/item.cpp | 17 ---- src/kademlia/node.cpp | 22 ++--- src/lsd.cpp | 119 +++++++++++++++++++-------- test/test_dht.cpp | 17 ++-- 11 files changed, 314 insertions(+), 127 deletions(-) create mode 100644 bindings/python/setup.py diff --git a/ChangeLog b/ChangeLog index c5b9f8bb0..624cef58b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 diff --git a/bindings/python/setup.py b/bindings/python/setup.py new file mode 100644 index 000000000..afd483160 --- /dev/null +++ b/bindings/python/setup.py @@ -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 +) + diff --git a/docs/dht_store.html b/docs/dht_store.html index 6e34abefc..00df7310e 100644 --- a/docs/dht_store.html +++ b/docs/dht_store.html @@ -57,18 +57,21 @@
  • mutable items
  • -
  • signature verification
  • -
  • expiration
  • -
  • test vectors

    This is a proposal for an extension to the BitTorrent DHT to allow @@ -220,7 +223,7 @@ the buffer to be signed is:

    { "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)> @@ -262,15 +265,25 @@ is intentional. When issuing a get 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.

    -

    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:

     {
    @@ -279,13 +292,13 @@ prevented based on the cas field if no value i
             "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:

     {
    @@ -329,7 +342,7 @@ 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.

    diff --git a/docs/dht_store.rst b/docs/dht_store.rst index 7deb533df..c5a5166b1 100644 --- a/docs/dht_store.rst +++ b/docs/dht_store.rst @@ -189,7 +189,7 @@ Request: { "a": { - "cas": **, + "cas": **, "id": *<20 byte id of sending node (string)>*, "k": **, "salt": ** @@ -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. diff --git a/include/libtorrent/kademlia/item.hpp b/include/libtorrent/kademlia/item.hpp index 7ec121376..350c7e466 100644 --- a/include/libtorrent/kademlia/item.hpp +++ b/include/libtorrent/kademlia/item.hpp @@ -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 v - , std::pair 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 const& pk() const { return m_pk; } diff --git a/include/libtorrent/lsd.hpp b/include/libtorrent/lsd.hpp index 7715a3151..061bf9420 100644 --- a/include/libtorrent/lsd.hpp +++ b/include/libtorrent/lsd.hpp @@ -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 diff --git a/src/broadcast_socket.cpp b/src/broadcast_socket.cpp index 7ec45da56..61d35eda7 100644 --- a/src/broadcast_socket.cpp +++ b/src/broadcast_socket.cpp @@ -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::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" diff --git a/src/kademlia/item.cpp b/src/kademlia/item.cpp index bc46a08a1..d58600887 100644 --- a/src/kademlia/item.cpp +++ b/src/kademlia/item.cpp @@ -150,15 +150,6 @@ void sign_mutable_item( ); } -sha1_hash mutable_item_cas(std::pair v - , std::pair 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(m_salt.c_str(), m_salt.size()), m_seq); -} - } } // namespace libtorrent::dht diff --git a/src/kademlia/node.cpp b/src/kademlia/node.cpp index d8b6c33be..864afd012 100644 --- a/src/kademlia/node.cpp +++ b/src/kademlia/node.cpp @@ -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())) diff --git a/src/lsd.cpp b/src/lsd.cpp index 86470d9a7..ff4a777a0 100644 --- a/src/lsd.cpp +++ b/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(); } diff --git a/test/test_dht.cpp b/test/test_dht.cpp index 9ca783a62..c65dfbefb 100644 --- a/test/test_dht.cpp +++ b/test/test_dht.cpp @@ -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)