From 8b3368da1f30189917d6de5a96cba3b2e57bbcf9 Mon Sep 17 00:00:00 2001 From: Miguel Freitas Date: Sun, 4 Aug 2013 16:16:36 -0300 Subject: [PATCH] draft for dht putdata --- libtorrent/src/kademlia/node.cpp | 157 +++++++++++++++++++++++++++++-- src/twister.cpp | 5 + src/twister.h | 1 + 3 files changed, 157 insertions(+), 6 deletions(-) diff --git a/libtorrent/src/kademlia/node.cpp b/libtorrent/src/kademlia/node.cpp index 933a134e..3042bf03 100644 --- a/libtorrent/src/kademlia/node.cpp +++ b/libtorrent/src/kademlia/node.cpp @@ -53,6 +53,8 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/kademlia/find_data.hpp" #include "libtorrent/rsa.hpp" +#include "../../src/twister.h" + namespace libtorrent { namespace dht { @@ -1033,6 +1035,148 @@ void node_impl::incoming_request(msg const& m, entry& e) } } } + else if (strcmp(query, "putData") == 0) + { + const static key_desc_t msg_desc[] = { + {"token", lazy_entry::string_t, 0, 0}, + {"sig_p", lazy_entry::string_t, 0, 0}, + {"sig_user", lazy_entry::string_t, 0, 0}, + {"p", lazy_entry::dict_t, 0, key_desc_t::parse_children}, + {"v", lazy_entry::none_t, 0, 0}, + {"seq", lazy_entry::int_t, 0, key_desc_t::optional}, + {"time", lazy_entry::int_t, 0, 0}, + {"height", lazy_entry::int_t, 0, 0}, + {"target", lazy_entry::dict_t, 0, key_desc_t::parse_children}, + {"n", lazy_entry::string_t, 0, 0}, + {"r", lazy_entry::string_t, 0, 0}, + {"t", lazy_entry::string_t, 0, 0}, + }; + enum {mk_token=0, mk_sig_p, mk_sig_user, mk_p, mk_v, + mk_seq, mk_time, mk_height, mk_target, mk_n, + mk_r, mk_t}; + + // attempt to parse the message + lazy_entry const* msg_keys[12]; + if (!verify_message(arg_ent, msg_desc, msg_keys, 12, error_string, sizeof(error_string))) + { + incoming_error(e, error_string); + return; + } + + // is this a multi-item? + bool multi = (msg_keys[mk_t]->string_value() == "m"); + + // pointer and length to the whole entry + std::pair buf = msg_keys[mk_p]->data_section(); + if (buf.second > 767 || buf.second <= 0) + { + incoming_error(e, "message too big"); + return; + } + + // "target" must be a dict of 3 entries + if (msg_keys[mk_target]->dict_size() != 3) { + incoming_error(e, "target dict size != 3"); + return; + } + + // target id is hash of bencoded dict "target" + std::pair targetbuf = msg_keys[1]->data_section(); + sha1_hash target = hasher(targetbuf.first,targetbuf.second).final(); + + fprintf(stderr, "PUT target: %s = {%s,%s,%s}\n" + , to_hex(target.to_string()).c_str() + , msg_keys[mk_n], msg_keys[mk_r], msg_keys[mk_t]); + + // verify the write-token. tokens are only valid to write to + // specific target hashes. it must match the one we got a "get" for + if (!verify_token(msg_keys[mk_token]->string_value(), (char const*)&target[0], m.addr)) + { + incoming_error(e, "invalid token"); + return; + } + + std::pair bufp = msg_keys[mk_p]->data_section(); + std::string str_p(bufp.first,bufp.second); + if (!verifySignature(str_p, + msg_keys[mk_sig_user]->string_value(), + msg_keys[mk_sig_p]->string_value())) { + incoming_error(e, "invalid signature"); + return; + } + + if (!multi && msg_keys[mk_sig_user]->string_value() != + msg_keys[mk_n]->string_value() ) { + incoming_error(e, "only owner is allowed"); + return; + } + + if (!multi || !msg_keys[mk_seq] || msg_keys[mk_seq]->int_value() <= 0) { + incoming_error(e, "seq is required"); + return; + } + + if (msg_keys[mk_height]->int_value() > getBestHeight() ) { + incoming_error(e, "future messages not allowed"); + return; + } + + dht_storage_table_t::iterator i = m_storage_table.find(target); + if (i == m_storage_table.end()) { + // make sure we don't add too many items + if (int(m_storage_table.size()) >= m_settings.max_dht_items) + { + // erase one? preferably a multi + } + + dht_storage_item item; + item.p = str_p; + item.sig_p = msg_keys[mk_sig_p]->string_value(); + item.sig_user = msg_keys[mk_sig_user]->string_value(); + + dht_storage_list_t to_add; + to_add.push_back(item); + + boost::tie(i, boost::tuples::ignore) = m_storage_table.insert( + std::make_pair(target, to_add)); + } else { + dht_storage_list_t & lsto = i->second; + + // if not multi, seq must increase + if(!multi) { + dht_storage_item &item = lsto[0]; + // FIXME: Implement + // if( msg_keys[mk_seq]->int_value() > lsto[0].p.seq ) etc + if( msg_keys[mk_seq]->int_value() ) { + item.p = str_p; + item.sig_p = msg_keys[mk_sig_p]->string_value(); + item.sig_user = msg_keys[mk_sig_user]->string_value(); + } else { + incoming_error(e, "old sequence number"); + return; + } + } else { + dht_storage_list_t::iterator j = lsto.begin(), end(lsto.end()); + for (; j != end; ++j) + { + // compare p contents before adding to the list + if( j->p == str_p ) break; + } + if(j == end) { + // new entry + dht_storage_item item; + item.p = str_p; + item.sig_p = msg_keys[mk_sig_p]->string_value(); + item.sig_user = msg_keys[mk_sig_user]->string_value(); + lsto.push_back(item); + } + } + } + + m_table.node_seen(id, m.addr, 0xffff); + + //f->last_seen = time_now(); + } else if (strcmp(query, "getData") == 0) { key_desc_t msg_desc[] = { @@ -1042,6 +1186,7 @@ void node_impl::incoming_request(msg const& m, entry& e) {"r", lazy_entry::string_t, 0, 0}, {"t", lazy_entry::string_t, 0, 0}, }; + enum {mk_justtoken=0, mk_target, mk_n, mk_r, mk_t}; // attempt to parse the message lazy_entry const* msg_keys[5]; @@ -1052,23 +1197,23 @@ void node_impl::incoming_request(msg const& m, entry& e) } // "target" must be a dict of 3 entries - if (msg_keys[1]->dict_size() != 3) { + if (msg_keys[mk_target]->dict_size() != 3) { incoming_error(e, "target dict size != 3"); return; } // target id is hash of bencoded dict "target" - std::pair buf = msg_keys[1]->data_section(); - sha1_hash target(std::string(buf.first,buf.second)); + std::pair targetbuf = msg_keys[mk_target]->data_section(); + sha1_hash target = hasher(targetbuf.first,targetbuf.second).final(); bool justtoken = false; - if (msg_keys[0] && msg_keys[0]->int_value() != 0) justtoken = true; + if (msg_keys[mk_justtoken] && msg_keys[mk_justtoken]->int_value() != 0) justtoken = true; fprintf(stderr, "GET target: %s = {%s,%s,%s}\n" , to_hex(target.to_string()).c_str() - , msg_keys[2], msg_keys[3], msg_keys[4]); + , msg_keys[mk_n], msg_keys[mk_r], msg_keys[mk_t]); - reply["token"] = generate_token(m.addr, msg_keys[0]->string_ptr()); + reply["token"] = generate_token(m.addr, target.to_string().c_str()); nodes_t n; // always return nodes as well as peers diff --git a/src/twister.cpp b/src/twister.cpp index d213f456..20133703 100644 --- a/src/twister.cpp +++ b/src/twister.cpp @@ -267,3 +267,8 @@ bool verifySignature(std::string const &strMessage, std::string const &strUserna return (pubkeyRec.GetID() == pubkey.GetID()); } + +int getBestHeight() +{ + return nBestHeight; +} diff --git a/src/twister.h b/src/twister.h index 25cde556..c4afb8fc 100644 --- a/src/twister.h +++ b/src/twister.h @@ -17,5 +17,6 @@ void stopSessionTorrent(); std::string createSignature(std::string &strMessage, std::string &strUsername); bool verifySignature(std::string const &strMessage, std::string const &strUsername, std::string const &strSign); +int getBestHeight(); #endif // TWISTER_H