# # patch "ChangeLog" # from [f3d65f60cc585499549c93f29ea1e8e79e41798d] # to [7eced76606bfb456d0015e674b666ecc2b62f46d] # # patch "netcmd.cc" # from [36e1f3cae4c4b0ac416d746d2895373068aa043a] # to [a7231f09224add93dd959915476088cc3fa951ba] # # patch "netcmd.hh" # from [ab57b4e82546eb7dd946605d4fb84363883e99d9] # to [5626696805eab24ff5bd23f114a749b3aa78645a] # # patch "netsync.cc" # from [db4dc72988745a0d40e7b90db4b02aceb1533697] # to [7cf6b787b43c2ab13abd1d2343e915f84778eddb] # --- ChangeLog +++ ChangeLog @@ -1,3 +1,10 @@ +2005-06-04 Timothy Brownawell + + * netcmd.{cc,hh}, netsync.cc: Move {read,write}_*_cmd_payload + to netcmd::{read,write}_*_cmd . + * netcmd.cc, netsync.cc: Compatibility infrastructure. + * netsync.cc: Interoperate with v4 servers. + 2005-06-03 Timothy Brownawell * automate.cc (print_some_output): Fix compiler warning. --- netcmd.cc +++ netcmd.cc @@ -50,6 +50,9 @@ cmd_code(bye_cmd) {} +netcmd::netcmd(u8 _version) : version(_version), cmd_code(bye_cmd) +{} + size_t netcmd::encoded_size() { string tmp; @@ -66,39 +69,63 @@ } void -write_netcmd(netcmd const & in, string & out) +netcmd::write(string & out) const { - out += static_cast(in.version); - out += static_cast(in.cmd_code); - insert_variable_length_string(in.payload, out); - adler32 check(reinterpret_cast(in.payload.data()), - in.payload.size()); + out += static_cast(version); + out += static_cast(cmd_code); + insert_variable_length_string(payload, out); + adler32 check(reinterpret_cast(payload.data()), payload.size()); insert_datum_lsb(check.sum(), out); } + +// last should be zero (doesn't mean we're compatible with version 0). +// The nonzero elements are the historical netsync/netcmd versions we can +// interoperate with. For interoperating with newer versions, assume +// compatibility and let the remote host make the call. +static u8 const compatible_versions[] = {4, 0}; + +bool is_compatible(u8 version) +{ + for(u8 const *x=compatible_versions; *x; ++x) + { + if(*x == version) + return true; + } + return false; +} bool -read_netcmd(string & inbuf, netcmd & out) +netcmd::read(string & inbuf) { size_t pos = 0; if (inbuf.size() < constants::netcmd_minsz) return false; - out.version = extract_datum_lsb(inbuf, pos, "netcmd protocol number"); - int v = constants::netcmd_current_protocol_version; - if (out.version != constants::netcmd_current_protocol_version) - throw bad_decode(F("protocol version mismatch: wanted '%d' got '%d'") - % widen(v) - % widen(out.version)); + u8 ver = extract_datum_lsb(inbuf, pos, "netcmd protocol number"); + int v = version; u8 cmd_byte = extract_datum_lsb(inbuf, pos, "netcmd code"); switch (cmd_byte) { - case static_cast(error_cmd): - case static_cast(bye_cmd): + // hello may be newer than expected, or one we're compatible with case static_cast(hello_cmd): + if (ver < version && !is_compatible(ver)) + throw bad_decode(F("protocol version mismatch: wanted '%d' got '%d'") + % widen(v) + % widen(ver)); + break; + // these may be older compatible versions case static_cast(anonymous_cmd): case static_cast(auth_cmd): + if (ver != version && (ver > version || !is_compatible(ver))) + throw bad_decode(F("protocol version mismatch: wanted '%d' got '%d'") + % widen(v) + % widen(ver)); + break; + // these must match exactly what's expected + case static_cast(error_cmd): + case static_cast(bye_cmd): case static_cast(confirm_cmd): case static_cast(refine_cmd): case static_cast(done_cmd): @@ -107,11 +134,16 @@ case static_cast(data_cmd): case static_cast(delta_cmd): case static_cast(nonexistant_cmd): - out.cmd_code = static_cast(cmd_byte); + if (ver != version) + throw bad_decode(F("protocol version mismatch: wanted '%d' got '%d'") + % widen(v) + % widen(ver)); break; default: throw bad_decode(F("unknown netcmd code 0x%x") % widen(cmd_byte)); } + cmd_code = static_cast(cmd_byte); + version = ver; // check to see if we have even enough bytes for a complete uleb128 size_t payload_len = 0; @@ -133,16 +165,16 @@ // Do this ourselves, so we can swap the strings instead of copying. require_bytes(inbuf, pos, payload_len, "netcmd payload"); inbuf.erase(0, pos); - out.payload=inbuf.substr(payload_len); + payload=inbuf.substr(payload_len); inbuf.erase(payload_len, inbuf.npos); - inbuf.swap(out.payload); + inbuf.swap(payload); pos=0; // they might have given us bogus data u32 checksum = extract_datum_lsb(inbuf, pos, "netcmd checksum"); inbuf.erase(0, pos); - adler32 check(reinterpret_cast(out.payload.data()), - out.payload.size()); + adler32 check(reinterpret_cast(payload.data()), + payload.size()); if (checksum != check.sum()) throw bad_decode(F("bad checksum 0x%x vs. 0x%x") % checksum % check.sum()); @@ -154,357 +186,369 @@ //////////////////////////////////////////// void -read_error_cmd_payload(std::string const & in, - std::string & errmsg) +netcmd::read_error_cmd(std::string & errmsg) const { size_t pos = 0; // syntax is: - extract_variable_length_string(in, errmsg, pos, "error netcmd, message"); - assert_end_of_buffer(in, pos, "error netcmd payload"); + extract_variable_length_string(payload, errmsg, pos, "error netcmd, message"); + assert_end_of_buffer(payload, pos, "error netcmd payload"); } void -write_error_cmd_payload(std::string const & errmsg, - std::string & out) +netcmd::write_error_cmd(std::string const & errmsg) { - insert_variable_length_string(errmsg, out); + cmd_code = error_cmd; + payload.clear(); + insert_variable_length_string(errmsg, payload); } void -read_hello_cmd_payload(string const & in, - rsa_keypair_id & server_keyname, +netcmd::read_hello_cmd(rsa_keypair_id & server_keyname, rsa_pub_key & server_key, - id & nonce) + id & nonce) const { size_t pos = 0; // syntax is: string skn_str, sk_str; - extract_variable_length_string(in, skn_str, pos, "hello netcmd, server key name"); + extract_variable_length_string(payload, skn_str, pos, + "hello netcmd, server key name"); server_keyname = rsa_keypair_id(skn_str); - extract_variable_length_string(in, sk_str, pos, "hello netcmd, server key"); + extract_variable_length_string(payload, sk_str, pos, + "hello netcmd, server key"); server_key = rsa_pub_key(sk_str); - nonce = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes, + nonce = id(extract_substring(payload, pos, + constants::merkle_hash_length_in_bytes, "hello netcmd, nonce")); - assert_end_of_buffer(in, pos, "hello netcmd payload"); + assert_end_of_buffer(payload, pos, "hello netcmd payload"); } void -write_hello_cmd_payload(rsa_keypair_id const & server_keyname, +netcmd::write_hello_cmd(rsa_keypair_id const & server_keyname, rsa_pub_key const & server_key, - id const & nonce, - string & out) + id const & nonce) { + cmd_code = hello_cmd; + payload.clear(); I(nonce().size() == constants::merkle_hash_length_in_bytes); - insert_variable_length_string(server_keyname(), out); - insert_variable_length_string(server_key(), out); - out += nonce(); + insert_variable_length_string(server_keyname(), payload); + insert_variable_length_string(server_key(), payload); + payload += nonce(); } void -read_anonymous_cmd_payload(std::string const & in, - protocol_role & role, +netcmd::read_anonymous_cmd(protocol_role & role, std::string & pattern, - id & nonce2) + id & nonce2) const { size_t pos = 0; // syntax is: - u8 role_byte = extract_datum_lsb(in, pos, "anonymous netcmd, role"); + u8 role_byte = extract_datum_lsb(payload, pos, "anonymous netcmd, role"); if (role_byte != static_cast(source_role) && role_byte != static_cast(sink_role) && role_byte != static_cast(source_and_sink_role)) throw bad_decode(F("unknown role specifier %d") % widen(role_byte)); role = static_cast(role_byte); - extract_variable_length_string(in, pattern, pos, "anonymous netcmd, pattern"); - nonce2 = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes, + extract_variable_length_string(payload, pattern, pos, + "anonymous netcmd, pattern"); + nonce2 = id(extract_substring(payload, pos, + constants::merkle_hash_length_in_bytes, "anonymous netcmd, nonce2")); - assert_end_of_buffer(in, pos, "anonymous netcmd payload"); + assert_end_of_buffer(payload, pos, "anonymous netcmd payload"); } void -write_anonymous_cmd_payload(protocol_role role, +netcmd::write_anonymous_cmd(protocol_role role, std::string const & pattern, - id const & nonce2, - std::string & out) + id const & nonce2) { + cmd_code = anonymous_cmd; I(nonce2().size() == constants::merkle_hash_length_in_bytes); - out += static_cast(role); - insert_variable_length_string(pattern, out); - out += nonce2(); + payload = static_cast(role); + insert_variable_length_string(pattern, payload); + payload += nonce2(); } void -read_auth_cmd_payload(string const & in, - protocol_role & role, +netcmd::read_auth_cmd(protocol_role & role, string & pattern, id & client, id & nonce1, id & nonce2, - string & signature) + string & signature) const { size_t pos = 0; // syntax is: // // - u8 role_byte = extract_datum_lsb(in, pos, "auth netcmd, role"); + u8 role_byte = extract_datum_lsb(payload, pos, "auth netcmd, role"); if (role_byte != static_cast(source_role) && role_byte != static_cast(sink_role) && role_byte != static_cast(source_and_sink_role)) throw bad_decode(F("unknown role specifier %d") % widen(role_byte)); role = static_cast(role_byte); - extract_variable_length_string(in, pattern, pos, "auth netcmd, pattern"); - client = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes, + extract_variable_length_string(payload, pattern, pos, "auth netcmd, pattern"); + client = id(extract_substring(payload, pos, + constants::merkle_hash_length_in_bytes, "auth netcmd, client identifier")); - nonce1 = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes, + nonce1 = id(extract_substring(payload, pos, + constants::merkle_hash_length_in_bytes, "auth netcmd, nonce1")); - nonce2 = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes, + nonce2 = id(extract_substring(payload, pos, + constants::merkle_hash_length_in_bytes, "auth netcmd, nonce2")); - extract_variable_length_string(in, signature, pos, "auth netcmd, signature"); - assert_end_of_buffer(in, pos, "auth netcmd payload"); + extract_variable_length_string(payload, signature, pos, + "auth netcmd, signature"); + assert_end_of_buffer(payload, pos, "auth netcmd payload"); } void -write_auth_cmd_payload(protocol_role role, +netcmd::write_auth_cmd(protocol_role role, string const & pattern, id const & client, id const & nonce1, id const & nonce2, - string const & signature, - string & out) + string const & signature) { + cmd_code = auth_cmd; I(client().size() == constants::merkle_hash_length_in_bytes); I(nonce1().size() == constants::merkle_hash_length_in_bytes); I(nonce2().size() == constants::merkle_hash_length_in_bytes); - out += static_cast(role); - insert_variable_length_string(pattern, out); - out += client(); - out += nonce1(); - out += nonce2(); - insert_variable_length_string(signature, out); + payload = static_cast(role); + insert_variable_length_string(pattern, payload); + payload += client(); + payload += nonce1(); + payload += nonce2(); + insert_variable_length_string(signature, payload); } void -read_confirm_cmd_payload(string const & in, - string & signature) +netcmd::read_confirm_cmd(string & signature) const { size_t pos = 0; // syntax is: - extract_variable_length_string(in, signature, pos, "confirm netcmd, signature"); - assert_end_of_buffer(in, pos, "confirm netcmd payload"); + extract_variable_length_string(payload, signature, pos, + "confirm netcmd, signature"); + assert_end_of_buffer(payload, pos, "confirm netcmd payload"); } void -write_confirm_cmd_payload(string const & signature, - string & out) +netcmd::write_confirm_cmd(string const & signature) { - insert_variable_length_string(signature, out); + cmd_code = confirm_cmd; + payload.clear(); + insert_variable_length_string(signature, payload); } void -read_refine_cmd_payload(string const & in, merkle_node & node) +netcmd::read_refine_cmd(merkle_node & node) const { // syntax is: - read_node(in, node); + read_node(payload, node); } void -write_refine_cmd_payload(merkle_node const & node, string & out) +netcmd::write_refine_cmd(merkle_node const & node) { - write_node(node, out); + cmd_code = refine_cmd; + payload.clear(); + write_node(node, payload); } void -read_done_cmd_payload(string const & in, - size_t & level, - netcmd_item_type & type) +netcmd::read_done_cmd(size_t & level, netcmd_item_type & type) const { size_t pos = 0; // syntax is: - level = extract_datum_uleb128(in, pos, "done netcmd, level number"); - type = read_netcmd_item_type(in, pos, "done netcmd, item type"); - assert_end_of_buffer(in, pos, "done netcmd payload"); + level = extract_datum_uleb128(payload, pos, + "done netcmd, level number"); + type = read_netcmd_item_type(payload, pos, "done netcmd, item type"); + assert_end_of_buffer(payload, pos, "done netcmd payload"); } void -write_done_cmd_payload(size_t level, - netcmd_item_type type, - string & out) +netcmd::write_done_cmd(size_t level, + netcmd_item_type type) { - insert_datum_uleb128(level, out); - out += static_cast(type); + cmd_code = done_cmd; + payload.clear(); + insert_datum_uleb128(level, payload); + payload += static_cast(type); } void -read_send_data_cmd_payload(string const & in, - netcmd_item_type & type, - id & item) +netcmd::read_send_data_cmd(netcmd_item_type & type, id & item) const { size_t pos = 0; // syntax is: - type = read_netcmd_item_type(in, pos, "send_data netcmd, item type"); - item = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes, + type = read_netcmd_item_type(payload, pos, "send_data netcmd, item type"); + item = id(extract_substring(payload, pos, + constants::merkle_hash_length_in_bytes, "send_data netcmd, item identifier")); - assert_end_of_buffer(in, pos, "send_data netcmd payload"); + assert_end_of_buffer(payload, pos, "send_data netcmd payload"); } void -write_send_data_cmd_payload(netcmd_item_type type, - id const & item, - string & out) +netcmd::write_send_data_cmd(netcmd_item_type type, id const & item) { + cmd_code = send_data_cmd; I(item().size() == constants::merkle_hash_length_in_bytes); - out += static_cast(type); - out += item(); + payload = static_cast(type); + payload += item(); } void -read_send_delta_cmd_payload(string const & in, - netcmd_item_type & type, +netcmd::read_send_delta_cmd(netcmd_item_type & type, id & base, - id & ident) + id & ident) const { size_t pos = 0; // syntax is: - type = read_netcmd_item_type(in, pos, "send_delta netcmd, item type"); - base = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes, + type = read_netcmd_item_type(payload, pos, "send_delta netcmd, item type"); + base = id(extract_substring(payload, pos, + constants::merkle_hash_length_in_bytes, "send_delta netcmd, base item identifier")); - ident = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes, + ident = id(extract_substring(payload, pos, + constants::merkle_hash_length_in_bytes, "send_delta netcmd, ident item identifier")); - assert_end_of_buffer(in, pos, "send_delta netcmd payload"); + assert_end_of_buffer(payload, pos, "send_delta netcmd payload"); } void -write_send_delta_cmd_payload(netcmd_item_type type, +netcmd::write_send_delta_cmd(netcmd_item_type type, id const & base, - id const & ident, - string & out) + id const & ident) { + cmd_code = send_delta_cmd; I(base().size() == constants::merkle_hash_length_in_bytes); I(ident().size() == constants::merkle_hash_length_in_bytes); - out += static_cast(type); - out += base(); - out += ident(); + payload = static_cast(type); + payload += base(); + payload += ident(); } void -read_data_cmd_payload(string const & in, - netcmd_item_type & type, - id & item, - string & dat) +netcmd::read_data_cmd(netcmd_item_type & type, + id & item, string & dat) const { size_t pos = 0; // syntax is: // - type = read_netcmd_item_type(in, pos, "data netcmd, item type"); - item = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes, + type = read_netcmd_item_type(payload, pos, "data netcmd, item type"); + item = id(extract_substring(payload, pos, + constants::merkle_hash_length_in_bytes, "data netcmd, item identifier")); dat.clear(); - u8 compressed_p = extract_datum_lsb(in, pos, "data netcmd, compression flag"); - extract_variable_length_string(in, dat, pos, "data netcmd, data payload"); + u8 compressed_p = extract_datum_lsb(payload, pos, + "data netcmd, compression flag"); + extract_variable_length_string(payload, dat, pos, + "data netcmd, data payload"); if (compressed_p == 1) dat = xform(dat); - assert_end_of_buffer(in, pos, "data netcmd payload"); + assert_end_of_buffer(payload, pos, "data netcmd payload"); } void -write_data_cmd_payload(netcmd_item_type type, +netcmd::write_data_cmd(netcmd_item_type type, id const & item, - string const & dat, - string & out) + string const & dat) { + cmd_code = data_cmd; I(item().size() == constants::merkle_hash_length_in_bytes); - out += static_cast(type); - out += item(); + payload = static_cast(type); + payload += item(); if (dat.size() > constants::netcmd_minimum_bytes_to_bother_with_gzip) { string tmp; tmp = xform(dat); - out += static_cast(1); // compressed flag - insert_variable_length_string(tmp, out); + payload += static_cast(1); // compressed flag + insert_variable_length_string(tmp, payload); } else { - out += static_cast(0); // compressed flag - insert_variable_length_string(dat, out); + payload += static_cast(0); // compressed flag + insert_variable_length_string(dat, payload); } } void -read_delta_cmd_payload(string const & in, - netcmd_item_type & type, - id & base, id & ident, delta & del) +netcmd::read_delta_cmd(netcmd_item_type & type, + id & base, id & ident, delta & del) const { size_t pos = 0; // syntax is: // - type = read_netcmd_item_type(in, pos, "delta netcmd, item type"); - base = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes, + type = read_netcmd_item_type(payload, pos, "delta netcmd, item type"); + base = id(extract_substring(payload, pos, + constants::merkle_hash_length_in_bytes, "delta netcmd, base identifier")); - ident = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes, + ident = id(extract_substring(payload, pos, + constants::merkle_hash_length_in_bytes, "delta netcmd, ident identifier")); - u8 compressed_p = extract_datum_lsb(in, pos, "delta netcmd, compression flag"); + u8 compressed_p = extract_datum_lsb(payload, pos, + "delta netcmd, compression flag"); string tmp; - extract_variable_length_string(in, tmp, pos, "delta netcmd, delta payload"); + extract_variable_length_string(payload, tmp, pos, + "delta netcmd, delta payload"); if (compressed_p == 1) tmp = xform(tmp); del = delta(tmp); - assert_end_of_buffer(in, pos, "delta netcmd payload"); + assert_end_of_buffer(payload, pos, "delta netcmd payload"); } void -write_delta_cmd_payload(netcmd_item_type & type, +netcmd::write_delta_cmd(netcmd_item_type & type, id const & base, id const & ident, - delta const & del, string & out) + delta const & del) { + cmd_code = delta_cmd; I(base().size() == constants::merkle_hash_length_in_bytes); I(ident().size() == constants::merkle_hash_length_in_bytes); - out += static_cast(type); - out += base(); - out += ident(); + payload = static_cast(type); + payload += base(); + payload += ident(); string tmp = del(); if (tmp.size() > constants::netcmd_minimum_bytes_to_bother_with_gzip) { - out += static_cast(1); // compressed flag + payload += static_cast(1); // compressed flag tmp = xform(tmp); } else { - out += static_cast(0); // compressed flag + payload += static_cast(0); // compressed flag } I(tmp.size() <= constants::netcmd_payload_limit); - insert_variable_length_string(tmp, out); + insert_variable_length_string(tmp, payload); } void -read_nonexistant_cmd_payload(string const & in, - netcmd_item_type & type, - id & item) +netcmd::read_nonexistant_cmd(netcmd_item_type & type, id & item) const { size_t pos = 0; // syntax is: - type = read_netcmd_item_type(in, pos, "nonexistant netcmd, item type"); - item = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes, + type = read_netcmd_item_type(payload, pos, "nonexistant netcmd, item type"); + item = id(extract_substring(payload, pos, + constants::merkle_hash_length_in_bytes, "nonexistant netcmd, item identifier")); - assert_end_of_buffer(in, pos, "nonexistant netcmd payload"); + assert_end_of_buffer(payload, pos, "nonexistant netcmd payload"); } void -write_nonexistant_cmd_payload(netcmd_item_type type, - id const & item, - string & out) +netcmd::write_nonexistant_cmd(netcmd_item_type type, id const & item) { + cmd_code = nonexistant_cmd; I(item().size() == constants::merkle_hash_length_in_bytes); - out += static_cast(type); - out += item(); + payload = static_cast(type); + payload += item(); } @@ -527,11 +571,10 @@ netcmd out_cmd, in_cmd; string out_errmsg("your shoelaces are untied"), in_errmsg; string buf; - out_cmd.cmd_code = error_cmd; - write_error_cmd_payload(out_errmsg, out_cmd.payload); - write_netcmd(out_cmd, buf); - BOOST_CHECK(read_netcmd(buf, in_cmd)); - read_error_cmd_payload(in_cmd.payload, in_errmsg); + out_cmd.write_error_cmd(out_errmsg); + out_cmd.write(buf); + BOOST_CHECK(in_cmd.read(buf)); + in_cmd.read_error_cmd(in_errmsg); BOOST_CHECK(in_cmd == out_cmd); BOOST_CHECK(in_errmsg == out_errmsg); L(F("errmsg_cmd test done, buffer was %d bytes\n") % buf.size()); @@ -542,9 +585,8 @@ L(F("checking i/o round trip on bye_cmd\n")); netcmd out_cmd, in_cmd; string buf; - out_cmd.cmd_code = bye_cmd; - write_netcmd(out_cmd, buf); - BOOST_CHECK(read_netcmd(buf, in_cmd)); + out_cmd.write(buf); + BOOST_CHECK(in_cmd.read(buf)); BOOST_CHECK(in_cmd == out_cmd); L(F("bye_cmd test done, buffer was %d bytes\n") % buf.size()); } @@ -557,11 +599,10 @@ rsa_keypair_id out_server_keyname("address@hidden"), in_server_keyname; rsa_pub_key out_server_key("9387938749238792874"), in_server_key; id out_nonce(raw_sha1("nonce it up")), in_nonce; - out_cmd.cmd_code = hello_cmd; - write_hello_cmd_payload(out_server_keyname, out_server_key, out_nonce, out_cmd.payload); - write_netcmd(out_cmd, buf); - BOOST_CHECK(read_netcmd(buf, in_cmd)); - read_hello_cmd_payload(in_cmd.payload, in_server_keyname, in_server_key, in_nonce); + out_cmd.write_hello_cmd(out_server_keyname, out_server_key, out_nonce); + out_cmd.write(buf); + BOOST_CHECK(in_cmd.read(buf)); + in_cmd.read_hello_cmd(in_server_keyname, in_server_key, in_nonce); BOOST_CHECK(in_cmd == out_cmd); BOOST_CHECK(in_server_keyname == out_server_keyname); BOOST_CHECK(in_server_key == out_server_key); @@ -578,11 +619,10 @@ id out_nonce2(raw_sha1("nonce start my heart")), in_nonce2; string out_pattern("radishes galore!"), in_pattern; - out_cmd.cmd_code = anonymous_cmd; - write_anonymous_cmd_payload(out_role, out_pattern, out_nonce2, out_cmd.payload); - write_netcmd(out_cmd, buf); - BOOST_CHECK(read_netcmd(buf, in_cmd)); - read_anonymous_cmd_payload(in_cmd.payload, in_role, in_pattern, in_nonce2); + out_cmd.write_anonymous_cmd(out_role, out_pattern, out_nonce2); + out_cmd.write(buf); + BOOST_CHECK(in_cmd.read(buf)); + in_cmd.read_anonymous_cmd(in_role, in_pattern, in_nonce2); BOOST_CHECK(in_cmd == out_cmd); BOOST_CHECK(in_nonce2 == out_nonce2); BOOST_CHECK(in_role == out_role); @@ -601,13 +641,12 @@ string out_signature(raw_sha1("burble") + raw_sha1("gorby")), out_pattern("radishes galore!"), in_signature, in_pattern; - out_cmd.cmd_code = auth_cmd; - write_auth_cmd_payload(out_role, out_pattern, out_client, out_nonce1, - out_nonce2, out_signature, out_cmd.payload); - write_netcmd(out_cmd, buf); - BOOST_CHECK(read_netcmd(buf, in_cmd)); - read_auth_cmd_payload(in_cmd.payload, in_role, in_pattern, in_client, - in_nonce1, in_nonce2, in_signature); + out_cmd.write_auth_cmd(out_role, out_pattern, out_client, out_nonce1, + out_nonce2, out_signature); + out_cmd.write(buf); + BOOST_CHECK(in_cmd.read(buf)); + in_cmd.read_auth_cmd(in_role, in_pattern, in_client, + in_nonce1, in_nonce2, in_signature); BOOST_CHECK(in_cmd == out_cmd); BOOST_CHECK(in_client == out_client); BOOST_CHECK(in_nonce1 == out_nonce1); @@ -624,11 +663,10 @@ string buf; string out_signature(raw_sha1("egg") + raw_sha1("tomago")), in_signature; - out_cmd.cmd_code = confirm_cmd; - write_confirm_cmd_payload(out_signature, out_cmd.payload); - write_netcmd(out_cmd, buf); - BOOST_CHECK(read_netcmd(buf, in_cmd)); - read_confirm_cmd_payload(in_cmd.payload, in_signature); + out_cmd.write_confirm_cmd(out_signature); + out_cmd.write(buf); + BOOST_CHECK(in_cmd.read(buf)); + in_cmd.read_confirm_cmd(in_signature); BOOST_CHECK(in_cmd == out_cmd); BOOST_CHECK(in_signature == out_signature); L(F("confirm_cmd test done, buffer was %d bytes\n") % buf.size()); @@ -650,11 +688,10 @@ out_node.set_slot_state(8, dead_leaf_state); out_node.set_slot_state(15, subtree_state); - out_cmd.cmd_code = refine_cmd; - write_refine_cmd_payload(out_node, out_cmd.payload); - write_netcmd(out_cmd, buf); - BOOST_CHECK(read_netcmd(buf, in_cmd)); - read_refine_cmd_payload(in_cmd.payload, in_node); + out_cmd.write_refine_cmd(out_node); + out_cmd.write(buf); + BOOST_CHECK(in_cmd.read(buf)); + in_cmd.read_refine_cmd(in_node); BOOST_CHECK(in_cmd == out_cmd); BOOST_CHECK(in_node == out_node); L(F("refine_cmd test done, buffer was %d bytes\n") % buf.size()); @@ -668,11 +705,10 @@ netcmd_item_type out_type(key_item), in_type(manifest_item); string buf; - out_cmd.cmd_code = done_cmd; - write_done_cmd_payload(out_level, out_type, out_cmd.payload); - write_netcmd(out_cmd, buf); - BOOST_CHECK(read_netcmd(buf, in_cmd)); - read_done_cmd_payload(in_cmd.payload, in_level, in_type); + out_cmd.write_done_cmd(out_level, out_type); + out_cmd.write(buf); + BOOST_CHECK(in_cmd.read(buf)); + in_cmd.read_done_cmd(in_level, in_type); BOOST_CHECK(in_level == out_level); BOOST_CHECK(in_type == out_type); L(F("done_cmd test done, buffer was %d bytes\n") % buf.size()); @@ -686,11 +722,10 @@ id out_id(raw_sha1("avocado is the yummiest")), in_id; string buf; - out_cmd.cmd_code = send_data_cmd; - write_send_data_cmd_payload(out_type, out_id, out_cmd.payload); - write_netcmd(out_cmd, buf); - BOOST_CHECK(read_netcmd(buf, in_cmd)); - read_send_data_cmd_payload(in_cmd.payload, in_type, in_id); + out_cmd.write_send_data_cmd(out_type, out_id); + out_cmd.write(buf); + BOOST_CHECK(in_cmd.read(buf)); + in_cmd.read_send_data_cmd(in_type, in_id); BOOST_CHECK(in_type == out_type); BOOST_CHECK(in_id == out_id); L(F("send_data_cmd test done, buffer was %d bytes\n") % buf.size()); @@ -705,11 +740,10 @@ id out_base(raw_sha1("always check the exit locations")), in_base; string buf; - out_cmd.cmd_code = send_delta_cmd; - write_send_delta_cmd_payload(out_type, out_head, out_base, out_cmd.payload); - write_netcmd(out_cmd, buf); - BOOST_CHECK(read_netcmd(buf, in_cmd)); - read_send_delta_cmd_payload(in_cmd.payload, in_type, in_head, in_base); + out_cmd.write_send_delta_cmd(out_type, out_head, out_base); + out_cmd.write(buf); + BOOST_CHECK(in_cmd.read(buf)); + in_cmd.read_send_delta_cmd(in_type, in_head, in_base); BOOST_CHECK(in_type == out_type); BOOST_CHECK(in_head == out_head); BOOST_CHECK(in_base == out_base); @@ -724,11 +758,10 @@ id out_id(raw_sha1("tuna is not yummy")), in_id; string out_dat("thank you for flying northwest"), in_dat; string buf; - out_cmd.cmd_code = data_cmd; - write_data_cmd_payload(out_type, out_id, out_dat, out_cmd.payload); - write_netcmd(out_cmd, buf); - BOOST_CHECK(read_netcmd(buf, in_cmd)); - read_data_cmd_payload(in_cmd.payload, in_type, in_id, in_dat); + out_cmd.write_data_cmd(out_type, out_id, out_dat); + out_cmd.write(buf); + BOOST_CHECK(in_cmd.read(buf)); + in_cmd.read_data_cmd(in_type, in_id, in_dat); BOOST_CHECK(in_id == out_id); BOOST_CHECK(in_dat == out_dat); L(F("data_cmd test done, buffer was %d bytes\n") % buf.size()); @@ -744,11 +777,10 @@ delta out_delta("goodness, this is not an xdelta"), in_delta; string buf; - out_cmd.cmd_code = delta_cmd; - write_delta_cmd_payload(out_type, out_head, out_base, out_delta, out_cmd.payload); - write_netcmd(out_cmd, buf); - BOOST_CHECK(read_netcmd(buf, in_cmd)); - read_delta_cmd_payload(in_cmd.payload, in_type, in_head, in_base, in_delta); + out_cmd.write_delta_cmd(out_type, out_head, out_base, out_delta); + out_cmd.write(buf); + BOOST_CHECK(in_cmd.read(buf)); + in_cmd.read_delta_cmd(in_type, in_head, in_base, in_delta); BOOST_CHECK(in_type == out_type); BOOST_CHECK(in_head == out_head); BOOST_CHECK(in_base == out_base); @@ -764,11 +796,10 @@ id out_id(raw_sha1("avocado is the yummiest")), in_id; string buf; - out_cmd.cmd_code = nonexistant_cmd; - write_send_data_cmd_payload(out_type, out_id, out_cmd.payload); - write_netcmd(out_cmd, buf); - BOOST_CHECK(read_netcmd(buf, in_cmd)); - read_send_data_cmd_payload(in_cmd.payload, in_type, in_id); + out_cmd.write_nonexistant_cmd(out_type, out_id); + out_cmd.write(buf); + BOOST_CHECK(in_cmd.read(buf)); + in_cmd.read_nonexistant_cmd(in_type, in_id); BOOST_CHECK(in_type == out_type); BOOST_CHECK(in_id == out_id); L(F("nonexistant_cmd test done, buffer was %d bytes\n") % buf.size()); --- netcmd.hh +++ netcmd.hh @@ -46,110 +46,99 @@ } netcmd_code; -struct netcmd +class netcmd { +private: u8 version; netcmd_code cmd_code; std::string payload; +public: netcmd(); + netcmd(u8 _version); + netcmd_code get_cmd_code() const {return cmd_code;} + u8 get_version() const {return version;} size_t encoded_size(); bool operator==(netcmd const & other) const; -}; -// basic cmd i/o (including checksums) -void write_netcmd(netcmd const & in, std::string & out); -bool read_netcmd(std::string & inbuf, netcmd & out); -// i/o functions for each type of command payload -void read_error_cmd_payload(std::string const & in, - std::string & errmsg); -void write_error_cmd_payload(std::string const & errmsg, - std::string & out); + // basic cmd i/o (including checksums) + void write(std::string & out) const; + bool read(std::string & inbuf); -void read_hello_cmd_payload(std::string const & in, - rsa_keypair_id & server_keyname, - rsa_pub_key & server_key, - id & nonce); -void write_hello_cmd_payload(rsa_keypair_id const & server_keyname, - rsa_pub_key const & server_key, - id const & nonce, - std::string & out); + // i/o functions for each type of command payload + void read_error_cmd(std::string & errmsg) const; + void write_error_cmd(std::string const & errmsg); -void read_anonymous_cmd_payload(std::string const & in, - protocol_role & role, - std::string & pattern, - id & nonce2); -void write_anonymous_cmd_payload(protocol_role role, - std::string const & pattern, - id const & nonce2, - std::string & out); +//void read_bye_cmd() {} + void write_bye_cmd() {cmd_code = bye_cmd;} -void read_auth_cmd_payload(std::string const & in, - protocol_role & role, - std::string & pattern, - id & client, - id & nonce1, - id & nonce2, - std::string & signature); -void write_auth_cmd_payload(protocol_role role, - std::string const & pattern, - id const & client, - id const & nonce1, - id const & nonce2, - std::string const & signature, - std::string & out); + void read_hello_cmd(rsa_keypair_id & server_keyname, + rsa_pub_key & server_key, + id & nonce) const; + void write_hello_cmd(rsa_keypair_id const & server_keyname, + rsa_pub_key const & server_key, + id const & nonce); -void read_confirm_cmd_payload(std::string const & in, - std::string & signature); -void write_confirm_cmd_payload(std::string const & signature, - std::string & out); + void read_anonymous_cmd(protocol_role & role, + std::string & pattern, + id & nonce2) const; + void write_anonymous_cmd(protocol_role role, + std::string const & pattern, + id const & nonce2); -void read_refine_cmd_payload(std::string const & in, merkle_node & node); -void write_refine_cmd_payload(merkle_node const & node, std::string & out); + void read_auth_cmd(protocol_role & role, + std::string & pattern, + id & client, + id & nonce1, + id & nonce2, + std::string & signature) const; + void write_auth_cmd(protocol_role role, + std::string const & pattern, + id const & client, + id const & nonce1, + id const & nonce2, + std::string const & signature); -void read_done_cmd_payload(std::string const & in, size_t & level, netcmd_item_type & type); -void write_done_cmd_payload(size_t level, netcmd_item_type type, std::string & out); + void read_confirm_cmd(std::string & signature) const; + void write_confirm_cmd(std::string const & signature); -void read_send_data_cmd_payload(std::string const & in, - netcmd_item_type & type, - id & item); -void write_send_data_cmd_payload(netcmd_item_type type, - id const & item, - std::string & out); + void read_refine_cmd(merkle_node & node) const; + void write_refine_cmd(merkle_node const & node); -void read_send_delta_cmd_payload(std::string const & in, - netcmd_item_type & type, - id & base, - id & ident); -void write_send_delta_cmd_payload(netcmd_item_type type, - id const & base, - id const & ident, - std::string & out); + void read_done_cmd(size_t & level, netcmd_item_type & type) const; + void write_done_cmd(size_t level, netcmd_item_type type); -void read_data_cmd_payload(std::string const & in, - netcmd_item_type & type, - id & item, - std::string & dat); -void write_data_cmd_payload(netcmd_item_type type, - id const & item, - std::string const & dat, - std::string & out); + void read_send_data_cmd(netcmd_item_type & type, + id & item) const; + void write_send_data_cmd(netcmd_item_type type, + id const & item); -void read_delta_cmd_payload(std::string const & in, - netcmd_item_type & type, - id & base, id & ident, - delta & del); -void write_delta_cmd_payload(netcmd_item_type & type, - id const & base, id const & ident, - delta const & del, - std::string & out); + void read_send_delta_cmd(netcmd_item_type & type, + id & base, + id & ident) const; + void write_send_delta_cmd(netcmd_item_type type, + id const & base, + id const & ident); -void read_nonexistant_cmd_payload(std::string const & in, - netcmd_item_type & type, - id & item); -void write_nonexistant_cmd_payload(netcmd_item_type type, - id const & item, - std::string & out); + void read_data_cmd(netcmd_item_type & type, + id & item, + std::string & dat) const; + void write_data_cmd(netcmd_item_type type, + id const & item, + std::string const & dat); + void read_delta_cmd(netcmd_item_type & type, + id & base, id & ident, + delta & del) const; + void write_delta_cmd(netcmd_item_type & type, + id const & base, id const & ident, + delta const & del); + void read_nonexistant_cmd(netcmd_item_type & type, + id & item) const; + void write_nonexistant_cmd(netcmd_item_type type, + id const & item); + +}; + #endif // __NETCMD_HH__ --- netsync.cc +++ netsync.cc @@ -221,6 +221,7 @@ string outbuf; netcmd cmd; + u8 protocol_version; bool armed; bool arm(); @@ -242,8 +243,7 @@ vector written_keys; vector written_certs; - map< std::pair, - boost::shared_ptr > merkle_tables; + map > merkle_tables; map done_refinements; map > > requested_items; @@ -276,6 +276,8 @@ id mk_nonce(); void mark_recent_io(); + void setup_client_tickers(); + bool done_all_refinements(); bool cert_refinement_done(); bool all_requested_revisions_received(); @@ -375,18 +377,15 @@ id const & item); bool merkle_node_exists(netcmd_item_type type, - utf8 const & pattern, size_t level, prefix const & pref); void load_merkle_node(netcmd_item_type type, - utf8 const & pattern, size_t level, prefix const & pref, merkle_ptr & node); void rebuild_merkle_trees(app_state & app, - utf8 const & pattern, set const & branches); bool dispatch_payload(netcmd const & cmd); @@ -433,6 +432,7 @@ str(sock, to), inbuf(""), outbuf(""), + protocol_version(constants::netcmd_current_protocol_version), armed(false), pattern(""), remote_peer_key_hash(""), @@ -576,6 +576,30 @@ last_io_time = ::time(NULL); } +void +session::setup_client_tickers() +{ + byte_in_ticker.reset(new ticker("bytes in", ">", 1024, true)); + byte_out_ticker.reset(new ticker("bytes out", "<", 1024, true)); + if (role == sink_role) + { + revision_checked_ticker.reset(new ticker("revs written", "w", 1)); + cert_in_ticker.reset(new ticker("certs in", "c", 3)); + revision_in_ticker.reset(new ticker("revs in", "r", 1)); + } + else if (role == source_role) + { + cert_out_ticker.reset(new ticker("certs out", "C", 3)); + revision_out_ticker.reset(new ticker("revs out", "R", 1)); + } + else + { + I(role == source_and_sink_role); + revision_checked_ticker.reset(new ticker("revs written", "w", 1)); + revision_in_ticker.reset(new ticker("revs in", "r", 1)); + revision_out_ticker.reset(new ticker("revs out", "R", 1)); + } +} bool session::done_all_refinements() @@ -701,7 +725,7 @@ session::write_netcmd_and_try_flush(netcmd const & cmd) { if (!encountered_error) - write_netcmd(cmd, outbuf); + cmd.write(outbuf); else L(F("dropping outgoing netcmd (because we're in error unwind mode)\n")); // FIXME: this helps keep the protocol pipeline full but it seems to @@ -1260,7 +1284,8 @@ { I(!outbuf.empty()); Netxx::signed_size_type count = str.write(outbuf.data(), - std::min(outbuf.size(), constants::bufsz)); + std::min(outbuf.size(), + constants::bufsz)); if(count > 0) { outbuf.erase(0, count); @@ -1287,8 +1312,8 @@ session::queue_bye_cmd() { L(F("queueing 'bye' command\n")); - netcmd cmd; - cmd.cmd_code = bye_cmd; + netcmd cmd(protocol_version); + cmd.write_bye_cmd(); write_netcmd_and_try_flush(cmd); this->sent_goodbye = true; } @@ -1297,9 +1322,8 @@ session::queue_error_cmd(string const & errmsg) { L(F("queueing 'error' command\n")); - netcmd cmd; - cmd.cmd_code = error_cmd; - write_error_cmd_payload(errmsg, cmd.payload); + netcmd cmd(protocol_version); + cmd.write_error_cmd(errmsg); write_netcmd_and_try_flush(cmd); this->sent_goodbye = true; } @@ -1311,9 +1335,8 @@ string typestr; netcmd_item_type_to_string(type, typestr); L(F("queueing 'done' command for %s level %s\n") % typestr % level); - netcmd cmd; - cmd.cmd_code = done_cmd; - write_done_cmd_payload(level, type, cmd.payload); + netcmd cmd(protocol_version); + cmd.write_done_cmd(level, type); write_netcmd_and_try_flush(cmd); } @@ -1321,8 +1344,7 @@ session::queue_hello_cmd(id const & server, id const & nonce) { - netcmd cmd; - cmd.cmd_code = hello_cmd; + netcmd cmd(protocol_version); hexenc server_encoded; encode_hexenc(server, server_encoded); @@ -1332,7 +1354,7 @@ app.db.get_pubkey(server_encoded, key_name, pub_encoded); decode_base64(pub_encoded, pub); - write_hello_cmd_payload(key_name, pub, nonce, cmd.payload); + cmd.write_hello_cmd(key_name, pub, nonce); write_netcmd_and_try_flush(cmd); } @@ -1341,9 +1363,8 @@ string const & pattern, id const & nonce2) { - netcmd cmd; - cmd.cmd_code = anonymous_cmd; - write_anonymous_cmd_payload(role, pattern, nonce2, cmd.payload); + netcmd cmd(protocol_version); + cmd.write_anonymous_cmd(role, pattern, nonce2); write_netcmd_and_try_flush(cmd); } @@ -1355,20 +1376,16 @@ id const & nonce2, string const & signature) { - netcmd cmd; - cmd.cmd_code = auth_cmd; - write_auth_cmd_payload(role, pattern, client, - nonce1, nonce2, signature, - cmd.payload); + netcmd cmd(protocol_version); + cmd.write_auth_cmd(role, pattern, client, nonce1, nonce2, signature); write_netcmd_and_try_flush(cmd); } void session::queue_confirm_cmd(string const & signature) { - netcmd cmd; - cmd.cmd_code = confirm_cmd; - write_confirm_cmd_payload(signature, cmd.payload); + netcmd cmd(protocol_version); + cmd.write_confirm_cmd(signature); write_netcmd_and_try_flush(cmd); } @@ -1381,9 +1398,8 @@ netcmd_item_type_to_string(node.type, typestr); L(F("queueing request for refinement of %s node '%s', level %d\n") % typestr % hpref % static_cast(node.level)); - netcmd cmd; - cmd.cmd_code = refine_cmd; - write_refine_cmd_payload(node, cmd.payload); + netcmd cmd(protocol_version); + cmd.write_refine_cmd(node); write_netcmd_and_try_flush(cmd); } @@ -1412,9 +1428,8 @@ L(F("queueing request for data of %s item '%s'\n") % typestr % hid); - netcmd cmd; - cmd.cmd_code = send_data_cmd; - write_send_data_cmd_payload(type, item, cmd.payload); + netcmd cmd(protocol_version); + cmd.write_send_data_cmd(type, item); write_netcmd_and_try_flush(cmd); note_item_requested(type, item); } @@ -1449,9 +1464,8 @@ L(F("queueing request for contents of %s delta '%s' -> '%s'\n") % typestr % base_hid % ident_hid); - netcmd cmd; - cmd.cmd_code = send_delta_cmd; - write_send_delta_cmd_payload(type, base, ident, cmd.payload); + netcmd cmd(protocol_version); + cmd.write_send_delta_cmd(type, base, ident); write_netcmd_and_try_flush(cmd); note_item_requested(type, ident); } @@ -1475,9 +1489,8 @@ L(F("queueing %d bytes of data for %s item '%s'\n") % dat.size() % typestr % hid); - netcmd cmd; - cmd.cmd_code = data_cmd; - write_data_cmd_payload(type, item, dat, cmd.payload); + netcmd cmd(protocol_version); + cmd.write_data_cmd(type, item, dat); write_netcmd_and_try_flush(cmd); note_item_sent(type, item); } @@ -1506,9 +1519,8 @@ L(F("queueing %s delta '%s' -> '%s'\n") % typestr % base_hid % ident_hid); - netcmd cmd; - cmd.cmd_code = delta_cmd; - write_delta_cmd_payload(type, base, ident, del, cmd.payload); + netcmd cmd(protocol_version); + cmd.write_delta_cmd(type, base, ident, del); write_netcmd_and_try_flush(cmd); note_item_sent(type, ident); } @@ -1530,9 +1542,8 @@ L(F("queueing note of nonexistance of %s item '%s'\n") % typestr % hid); - netcmd cmd; - cmd.cmd_code = nonexistant_cmd; - write_nonexistant_cmd_payload(type, item, cmd.payload); + netcmd cmd(protocol_version); + cmd.write_nonexistant_cmd(type, item); write_netcmd_and_try_flush(cmd); } @@ -1600,6 +1611,39 @@ return true; } +void +get_branches(app_state & app, vector & names) +{ + vector< revision > certs; + app.db.get_revision_certs(branch_cert_name, certs); + for (size_t i = 0; i < certs.size(); ++i) + { + cert_value name; + decode_base64(idx(certs, i).inner().value, name); + names.push_back(name()); + } + sort(names.begin(), names.end()); + names.erase(std::unique(names.begin(), names.end()), names.end()); + if(!names.size()) + W(F("No branches found.")); +} + +utf8 +convert_pattern(utf8 & pat) +{ + string x=pat(); + string pattern=""; + string e=".|*?+()[]{}^$\\"; + for(string::const_iterator i=x.begin(); i!=x.end(); i++) + { + if(e.find(*i) != e.npos) + pattern+='\\'; + pattern+=*i; + } + return utf8(pattern+".*"); +} + + static const var_domain known_servers_domain = var_domain("known-servers"); bool @@ -1662,7 +1706,24 @@ decode_hexenc(their_key_hash, their_key_hash_decoded); this->remote_peer_key_hash = their_key_hash_decoded; } - + + vector branchnames; + set ok_branches; + get_branches(app, branchnames); + utf8 pat(pattern); + if(protocol_version == 4) + pat=convert_pattern(pattern); + boost::regex reg(pat()); + for(vector::const_iterator i=branchnames.begin(); + i!=branchnames.end(); i++) + { + if(boost::regex_match(*i, reg)) + ok_branches.insert(utf8(*i)); + } + rebuild_merkle_trees(app, ok_branches); + + setup_client_tickers(); + if (app.signing_key() != "") { // get our public key for its hash identifier @@ -1703,23 +1764,6 @@ return false; } -void -get_branches(app_state & app, vector & names) -{ - vector< revision > certs; - app.db.get_revision_certs(branch_cert_name, certs); - for (size_t i = 0; i < certs.size(); ++i) - { - cert_value name; - decode_base64(idx(certs, i).inner().value, name); - names.push_back(name()); - } - sort(names.begin(), names.end()); - names.erase(std::unique(names.begin(), names.end()), names.end()); - if(!names.size()) - W(F("No branches found.")); -} - bool session::process_anonymous_cmd(protocol_role role, string const & pattern, @@ -1792,7 +1836,7 @@ P(F("allowed anonymous read permission for '%s'\n") % pattern); - rebuild_merkle_trees(app, pattern, ok_branches); + rebuild_merkle_trees(app, ok_branches); // get our private key and sign back L(F("anonymous read permitted, signing back nonce\n")); @@ -1936,7 +1980,7 @@ P(F("allowed '%s' write permission for '%s'\n") % their_id % pattern); } - rebuild_merkle_trees(app, pattern, ok_branches); + rebuild_merkle_trees(app, ok_branches); // save their identity this->remote_peer_key_hash = client; @@ -2011,15 +2055,15 @@ this->authenticated = true; merkle_ptr root; - load_merkle_node(epoch_item, this->pattern, 0, get_root_prefix().val, root); + load_merkle_node(epoch_item, 0, get_root_prefix().val, root); queue_refine_cmd(*root); queue_done_cmd(0, epoch_item); - load_merkle_node(key_item, this->pattern, 0, get_root_prefix().val, root); + load_merkle_node(key_item, 0, get_root_prefix().val, root); queue_refine_cmd(*root); queue_done_cmd(0, key_item); - load_merkle_node(cert_item, this->pattern, 0, get_root_prefix().val, root); + load_merkle_node(cert_item, 0, get_root_prefix().val, root); queue_refine_cmd(*root); queue_done_cmd(0, cert_item); return true; @@ -2176,8 +2220,7 @@ L(F("received 'refine' netcmd on %s node '%s', level %d\n") % typestr % hpref % lev); - if (!merkle_node_exists(their_node.type, this->pattern, - their_node.level, pref)) + if (!merkle_node_exists(their_node.type, their_node.level, pref)) { L(F("no corresponding %s merkle node for prefix '%s', level %d\n") % typestr % hpref % lev); @@ -2237,8 +2280,7 @@ L(F("found corresponding %s merkle node for prefix '%s', level %d\n") % typestr % hpref % lev); merkle_ptr our_node; - load_merkle_node(their_node.type, this->pattern, - their_node.level, pref, our_node); + load_merkle_node(their_node.type, their_node.level, pref, our_node); for (size_t slot = 0; slot < constants::merkle_num_slots; ++slot) { switch (their_node.get_slot_state(slot)) @@ -2284,8 +2326,8 @@ our_node->extended_raw_prefix(slot, subprefix); merkle_ptr our_subtree; I(our_node->type == their_node.type); - load_merkle_node(their_node.type, this->pattern, - our_node->level + 1, subprefix, our_subtree); + load_merkle_node(their_node.type, our_node->level + 1, + subprefix, our_subtree); I(our_node->type == our_subtree->type); queue_refine_cmd(*our_subtree); } @@ -2384,8 +2426,8 @@ prefix subprefix; our_node->extended_raw_prefix(slot, subprefix); merkle_ptr our_subtree; - load_merkle_node(our_node->type, this->pattern, - our_node->level + 1, subprefix, our_subtree); + load_merkle_node(our_node->type, our_node->level + 1, + subprefix, our_subtree); queue_refine_cmd(*our_subtree); } break; @@ -2444,8 +2486,8 @@ prefix subprefix; our_node->extended_raw_prefix(slot, subprefix); merkle_ptr our_subtree; - load_merkle_node(our_node->type, this->pattern, - our_node->level + 1, subprefix, our_subtree); + load_merkle_node(our_node->type, our_node->level + 1, + subprefix, our_subtree); queue_refine_cmd(*our_subtree); } break; @@ -2533,8 +2575,8 @@ prefix subprefix; our_node->extended_raw_prefix(slot, subprefix); merkle_ptr our_subtree; - load_merkle_node(our_node->type, this->pattern, - our_node->level + 1, subprefix, our_subtree); + load_merkle_node(our_node->type, our_node->level + 1, + subprefix, our_subtree); queue_refine_cmd(*our_subtree); } } @@ -2876,13 +2918,11 @@ bool session::merkle_node_exists(netcmd_item_type type, - utf8 const & pattern, size_t level, prefix const & pref) { - map< std::pair, - boost::shared_ptr >::const_iterator i = - merkle_tables.find(std::make_pair(pattern,type)); + map >::const_iterator i = + merkle_tables.find(type); I(i != merkle_tables.end()); merkle_table::const_iterator j = i->second->find(std::make_pair(pref, level)); @@ -2891,15 +2931,13 @@ void session::load_merkle_node(netcmd_item_type type, - utf8 const & pattern, size_t level, prefix const & pref, merkle_ptr & node) { - map< std::pair, - boost::shared_ptr >::const_iterator i = - merkle_tables.find(std::make_pair(pattern,type)); - + map >::const_iterator i = + merkle_tables.find(type); + I(i != merkle_tables.end()); merkle_table::const_iterator j = i->second->find(std::make_pair(pref, level)); I(j != i->second->end()); @@ -2911,7 +2949,7 @@ session::dispatch_payload(netcmd const & cmd) { - switch (cmd.cmd_code) + switch (cmd.get_cmd_code()) { case bye_cmd: @@ -2921,7 +2959,7 @@ case error_cmd: { string errmsg; - read_error_cmd_payload(cmd.payload, errmsg); + cmd.read_error_cmd(errmsg); return process_error_cmd(errmsg); } break; @@ -2933,7 +2971,9 @@ rsa_keypair_id server_keyname; rsa_pub_key server_key; id nonce; - read_hello_cmd_payload(cmd.payload, server_keyname, server_key, nonce); + cmd.read_hello_cmd(server_keyname, server_key, nonce); + if(cmd.get_version() < protocol_version) + protocol_version = cmd.get_version(); return process_hello_cmd(server_keyname, server_key, nonce); } break; @@ -2948,7 +2988,9 @@ protocol_role role; string pattern; id nonce2; - read_anonymous_cmd_payload(cmd.payload, role, pattern, nonce2); + cmd.read_anonymous_cmd(role, pattern, nonce2); + if(cmd.get_version() < protocol_version) + protocol_version = cmd.get_version(); return process_anonymous_cmd(role, pattern, nonce2); } break; @@ -2960,8 +3002,11 @@ protocol_role role; string pattern, signature; id client, nonce1, nonce2; - read_auth_cmd_payload(cmd.payload, role, pattern, client, nonce1, nonce2, signature); - return process_auth_cmd(role, pattern, client, nonce1, nonce2, signature); + cmd.read_auth_cmd(role, pattern, client, nonce1, nonce2, signature); + if(cmd.get_version() < protocol_version) + protocol_version = cmd.get_version(); + return process_auth_cmd(role, pattern, client, + nonce1, nonce2, signature); } break; @@ -2970,7 +3015,7 @@ require(voice == client_voice, "confirm netcmd received in client voice"); { string signature; - read_confirm_cmd_payload(cmd.payload, signature); + cmd.read_confirm_cmd(signature); return process_confirm_cmd(signature); } break; @@ -2979,7 +3024,7 @@ require(authenticated, "refine netcmd received when authenticated"); { merkle_node node; - read_refine_cmd_payload(cmd.payload, node); + cmd.read_refine_cmd(node); map< netcmd_item_type, done_marker>::iterator i = done_refinements.find(node.type); require(i != done_refinements.end(), "refinement netcmd refers to valid type"); require(i->second.tree_is_done == false, "refinement netcmd received when tree is live"); @@ -2993,7 +3038,7 @@ { size_t level; netcmd_item_type type; - read_done_cmd_payload(cmd.payload, level, type); + cmd.read_done_cmd(level, type); return process_done_cmd(level, type); } break; @@ -3006,7 +3051,7 @@ { netcmd_item_type type; id item; - read_send_data_cmd_payload(cmd.payload, type, item); + cmd.read_send_data_cmd(type, item); return process_send_data_cmd(type, item); } break; @@ -3019,7 +3064,7 @@ { netcmd_item_type type; id base, ident; - read_send_delta_cmd_payload(cmd.payload, type, base, ident); + cmd.read_send_delta_cmd(type, base, ident); return process_send_delta_cmd(type, base, ident); } @@ -3032,7 +3077,7 @@ netcmd_item_type type; id item; string dat; - read_data_cmd_payload(cmd.payload, type, item, dat); + cmd.read_data_cmd(type, item, dat); return process_data_cmd(type, item, dat); } break; @@ -3046,7 +3091,7 @@ netcmd_item_type type; id base, ident; delta del; - read_delta_cmd_payload(cmd.payload, type, base, ident, del); + cmd.read_delta_cmd(type, base, ident, del); return process_delta_cmd(type, base, ident, del); } break; @@ -3059,7 +3104,7 @@ { netcmd_item_type type; id item; - read_nonexistant_cmd_payload(cmd.payload, type, item); + cmd.read_nonexistant_cmd(type, item); return process_nonexistant_cmd(type, item); } break; @@ -3093,7 +3138,7 @@ { if (!armed) { - if (read_netcmd(inbuf, cmd)) + if (cmd.read(inbuf)) { // inbuf.erase(0, cmd.encoded_size()); armed = true; @@ -3144,39 +3189,6 @@ Netxx::Stream server(address().c_str(), default_port, timeout); session sess(role, client_voice, patterns, app, address(), server.get_socketfd(), timeout); - - vector branchnames; - set ok_branches; - get_branches(app, branchnames); - boost::regex reg(idx(patterns, 0)()); - for(vector::const_iterator i=branchnames.begin(); - i!=branchnames.end(); i++) - { - if(boost::regex_match(*i, reg)) - ok_branches.insert(utf8(*i)); - } - sess.rebuild_merkle_trees(app, idx(patterns, 0)(), ok_branches); - - sess.byte_in_ticker.reset(new ticker("bytes in", ">", 1024, true)); - sess.byte_out_ticker.reset(new ticker("bytes out", "<", 1024, true)); - if (role == sink_role) - { - sess.revision_checked_ticker.reset(new ticker("revs written", "w", 1)); - sess.cert_in_ticker.reset(new ticker("certs in", "c", 3)); - sess.revision_in_ticker.reset(new ticker("revs in", "r", 1)); - } - else if (role == source_role) - { - sess.cert_out_ticker.reset(new ticker("certs out", "C", 3)); - sess.revision_out_ticker.reset(new ticker("revs out", "R", 1)); - } - else - { - I(role == source_and_sink_role); - sess.revision_checked_ticker.reset(new ticker("revs written", "w", 1)); - sess.revision_in_ticker.reset(new ticker("revs in", "r", 1)); - sess.revision_out_ticker.reset(new ticker("revs out", "R", 1)); - } while (true) { @@ -3532,7 +3544,6 @@ static boost::shared_ptr make_root_node(session & sess, - utf8 const & pat, netcmd_item_type ty) { boost::shared_ptr tab = @@ -3543,7 +3554,7 @@ tab->insert(std::make_pair(std::make_pair(get_root_prefix().val, 0), tmp)); - sess.merkle_tables[std::make_pair(pat, ty)] = tab; + sess.merkle_tables[ty] = tab; return tab; } @@ -3577,17 +3588,16 @@ void session::rebuild_merkle_trees(app_state & app, - utf8 const & pattern, set const & branchnames) { - P(F("rebuilding merkle trees for pattern %s\n") % pattern); + P(F("rebuilding merkle trees ...\n")); for(set::const_iterator i=branchnames.begin(); i!=branchnames.end(); ++i) P(F("including branch %s") % *i); - boost::shared_ptr ctab = make_root_node(*this, pattern, cert_item); - boost::shared_ptr ktab = make_root_node(*this, pattern, key_item); - boost::shared_ptr etab = make_root_node(*this, pattern, epoch_item); + boost::shared_ptr ctab = make_root_node(*this, cert_item); + boost::shared_ptr ktab = make_root_node(*this, key_item); + boost::shared_ptr etab = make_root_node(*this, epoch_item); ticker certs_ticker("certs", "c", 256); ticker keys_ticker("keys", "k", 1);