#
# patch "ChangeLog"
# from [746912cbb100ebc57364b0e9c8d3785cb3cc5f7d]
# to [c472ec862675aabab5b00c7a463564a22747966c]
#
# patch "netcmd.cc"
# from [75a0d51313f112ec54f83d29eca1d1077d2547bb]
# to [38e6b3a85549ed7c7e5f109623d9ea1b802fc340]
#
# patch "netcmd.hh"
# from [8bea78d5e3429c65cc158c90450a7473528ceb07]
# to [87007edfa58287e177df2f3246b28eaa5c5f6146]
#
# patch "netsync.cc"
# from [5a4a894840cdd806535dd34121a150ea8d7a0870]
# to [f29b8cf04f7f4ef176165d31cd446c359233007a]
#
========================================================================
--- ChangeLog 746912cbb100ebc57364b0e9c8d3785cb3cc5f7d
+++ ChangeLog c472ec862675aabab5b00c7a463564a22747966c
@@ -1,3 +1,12 @@
+2005-09-16 Timothy Brownawell
+
+ * netcmd.{cc,hh}, netsync.cc: new netcmd types: usher_cmd and
+ usher_reply_cmd. They are not included in the HMAC, and do not
+ occur during normal communication. Purpose: running multiple servers
+ from the same port. This allows a special server to ask for the
+ client's include pattern, and then forward the connection to a real
+ monotone server.
+
2005-09-15 Timothy Brownawell
* app_state.{cc,hh}: restrictions now understand --exclude
========================================================================
--- netcmd.cc 75a0d51313f112ec54f83d29eca1d1077d2547bb
+++ netcmd.cc 38e6b3a85549ed7c7e5f109623d9ea1b802fc340
@@ -62,7 +62,8 @@
cmd_code == other.cmd_code &&
payload == other.payload;
}
-
+
+// note: usher_reply_cmd does not get included in the hmac.
void
netcmd::write(string & out, chained_hmac & hmac) const
{
@@ -71,11 +72,15 @@
out += static_cast(cmd_code);
insert_variable_length_string(payload, out);
- string digest = hmac.process(out, oldlen);
- I(hmac.hmac_length == constants::netsync_hmac_value_length_in_bytes);
- out.append(digest);
+ if (cmd_code != usher_reply_cmd)
+ {
+ string digest = hmac.process(out, oldlen);
+ I(hmac.hmac_length == constants::netsync_hmac_value_length_in_bytes);
+ out.append(digest);
+ }
}
+// note: usher_cmd does not get included in the hmac.
bool
netcmd::read(string_queue & inbuf, chained_hmac & hmac)
{
@@ -107,6 +112,7 @@
case static_cast(data_cmd):
case static_cast(delta_cmd):
case static_cast(nonexistant_cmd):
+ case static_cast(usher_cmd):
cmd_code = static_cast(cmd_byte);
break;
default:
@@ -124,21 +130,30 @@
throw bad_decode(F("oversized payload of '%d' bytes") % payload_len);
// there might not be enough data yet in the input buffer
- if (inbuf.size() < pos + payload_len + constants::netsync_hmac_value_length_in_bytes)
+ unsigned int minsize;
+ if (cmd_code == usher_cmd)
+ minsize = pos + payload_len;
+ else
+ minsize = pos + payload_len + constants::netsync_hmac_value_length_in_bytes;
+ if (inbuf.size() < minsize)
{
return false;
}
// grab it before the data gets munged
I(hmac.hmac_length == constants::netsync_hmac_value_length_in_bytes);
- string digest = hmac.process(inbuf, 0, pos + payload_len);
+ string digest;
+ if (cmd_code != usher_cmd)
+ digest = hmac.process(inbuf, 0, pos + payload_len);
payload = extract_substring(inbuf, pos, payload_len, "netcmd payload");
// they might have given us bogus data
- string cmd_digest = extract_substring(inbuf, pos,
- constants::netsync_hmac_value_length_in_bytes,
- "netcmd HMAC");
+ string cmd_digest;
+ if (cmd_code != usher_cmd)
+ cmd_digest = extract_substring(inbuf, pos,
+ constants::netsync_hmac_value_length_in_bytes,
+ "netcmd HMAC");
inbuf.pop_front(pos);
if (cmd_digest != digest)
throw bad_decode(F("bad HMAC checksum (got %s, wanted %s)\n"
@@ -544,7 +559,25 @@
payload += item();
}
+void
+netcmd::read_usher_cmd(utf8 & greeting) const
+{
+ size_t pos = 0;
+ std::string str;
+ extract_variable_length_string(payload, str, pos, "error netcmd, message");
+ greeting = utf8(str);
+ assert_end_of_buffer(payload, pos, "error netcmd payload");
+}
+void
+netcmd::write_usher_reply_cmd(utf8 const & pattern)
+{
+ cmd_code = usher_reply_cmd;
+ payload.clear();
+ insert_variable_length_string(pattern(), payload);
+}
+
+
#ifdef BUILD_UNIT_TESTS
#include "unit_tests.hh"
========================================================================
--- netcmd.hh 8bea78d5e3429c65cc158c90450a7473528ceb07
+++ netcmd.hh 87007edfa58287e177df2f3246b28eaa5c5f6146
@@ -44,7 +44,16 @@
send_delta_cmd = 9,
data_cmd = 10,
delta_cmd = 11,
- nonexistant_cmd = 12
+ nonexistant_cmd = 12,
+
+ // usher commands
+ // usher_cmd is sent by a server farm (or anyone else who wants to serve
+ // from multiple databases over the same port), and the reply (containing
+ // the client's include pattern) is used to choose a server to forward the
+ // connection to.
+ // usher_cmd is never sent by the monotone server itself.
+ usher_cmd = 100,
+ usher_reply_cmd = 101
}
netcmd_code;
@@ -158,6 +167,9 @@
void write_nonexistant_cmd(netcmd_item_type type,
id const & item);
+ void read_usher_cmd(utf8 & greeting) const;
+ void write_usher_reply_cmd(utf8 const & pattern);
+
};
#endif // __NETCMD_HH__
========================================================================
--- netsync.cc 5a4a894840cdd806535dd34121a150ea8d7a0870
+++ netsync.cc f29b8cf04f7f4ef176165d31cd446c359233007a
@@ -442,6 +442,7 @@
delta const & del);
bool process_nonexistant_cmd(netcmd_item_type type,
id const & item);
+ bool process_usher_cmd(utf8 const & msg);
bool merkle_node_exists(netcmd_item_type type,
size_t level,
@@ -2976,6 +2977,23 @@
}
bool
+session::process_usher_cmd(utf8 const & msg)
+{
+ if (greeting().size())
+ {
+ if (greeting()[0] == '!')
+ P(F("Received warning from usher: %s") % greeting().substr(1));
+ else
+ L(F("Received greeting from usher: %s") % greeting().substr(1));
+ }
+ netcmd cmdout;
+ cmdout.write_usher_reply_cmd(our_include_pattern);
+ write_netcmd_and_try_flush(cmdout);
+ L(F("Sent reply."));
+ return true;
+}
+
+bool
session::merkle_node_exists(netcmd_item_type type,
size_t level,
prefix const & pref)
@@ -3193,6 +3211,16 @@
return process_nonexistant_cmd(type, item);
}
break;
+ case usher_cmd:
+ {
+ utf8 greeting;
+ cmd.read_usher_cmd(greeting);
+ return process_usher_cmd(greeting);
+ }
+ break;
+ case usher_reply_cmd:
+ return false;// should not happen
+ break;
}
return false;
}