monotone

monotone Mtn Source Tree

Root/netcmd.cc

1// copyright (C) 2004 graydon hoare <graydon@pobox.com>
2// all rights reserved.
3// licensed to the public under the terms of the GNU GPL (>= 2)
4// see the file COPYING for details
5
6#include <string>
7#include <vector>
8#include <utility>
9
10#include "cryptopp/gzip.h"
11
12#include "adler32.hh"
13#include "constants.hh"
14#include "netcmd.hh"
15#include "netio.hh"
16#include "numeric_vocab.hh"
17#include "sanity.hh"
18#include "transforms.hh"
19
20using namespace std;
21using namespace boost;
22
23static netcmd_item_type
24read_netcmd_item_type(string const & in,
25 size_t & pos,
26 string const & name)
27{
28 u8 tmp = extract_datum_lsb<u8>(in, pos, name);
29 switch (tmp)
30 {
31 case static_cast<u8>(revision_item):
32 return revision_item;
33 case static_cast<u8>(manifest_item):
34 return manifest_item;
35 case static_cast<u8>(file_item):
36 return file_item;
37 case static_cast<u8>(cert_item):
38 return cert_item;
39 case static_cast<u8>(key_item):
40 return key_item;
41 case static_cast<u8>(epoch_item):
42 return epoch_item;
43 default:
44 throw bad_decode(F("unknown item type 0x%x for '%s'")
45 % static_cast<int>(tmp) % name);
46 }
47}
48
49netcmd::netcmd() : version(constants::netcmd_current_protocol_version),
50 cmd_code(bye_cmd)
51{}
52
53size_t netcmd::encoded_size()
54{
55 string tmp;
56 insert_datum_uleb128<size_t>(payload.size(), tmp);
57 return 1 + 1 + tmp.size() + payload.size() + 4;
58}
59
60bool
61netcmd::operator==(netcmd const & other) const
62{
63 return version == other.version &&
64 cmd_code == other.cmd_code &&
65 payload == other.payload;
66}
67
68void
69write_netcmd(netcmd const & in, string & out)
70{
71 out += static_cast<char>(in.version);
72 out += static_cast<char>(in.cmd_code);
73 insert_variable_length_string(in.payload, out);
74 adler32 check(reinterpret_cast<u8 const *>(in.payload.data()),
75 in.payload.size());
76 insert_datum_lsb<u32>(check.sum(), out);
77}
78
79bool
80read_netcmd(string & inbuf, netcmd & out)
81{
82 size_t pos = 0;
83
84 if (inbuf.size() < constants::netcmd_minsz)
85 return false;
86
87 out.version = extract_datum_lsb<u8>(inbuf, pos, "netcmd protocol number");
88 int v = constants::netcmd_current_protocol_version;
89 if (out.version != constants::netcmd_current_protocol_version)
90 throw bad_decode(F("protocol version mismatch: wanted '%d' got '%d'")
91 % widen<u32,u8>(v)
92 % widen<u32,u8>(out.version));
93
94 u8 cmd_byte = extract_datum_lsb<u8>(inbuf, pos, "netcmd code");
95 switch (cmd_byte)
96 {
97 case static_cast<u8>(error_cmd):
98 case static_cast<u8>(bye_cmd):
99 case static_cast<u8>(hello_cmd):
100 case static_cast<u8>(anonymous_cmd):
101 case static_cast<u8>(auth_cmd):
102 case static_cast<u8>(confirm_cmd):
103 case static_cast<u8>(refine_cmd):
104 case static_cast<u8>(done_cmd):
105 case static_cast<u8>(send_data_cmd):
106 case static_cast<u8>(send_delta_cmd):
107 case static_cast<u8>(data_cmd):
108 case static_cast<u8>(delta_cmd):
109 case static_cast<u8>(nonexistant_cmd):
110 out.cmd_code = static_cast<netcmd_code>(cmd_byte);
111 break;
112 default:
113 throw bad_decode(F("unknown netcmd code 0x%x") % widen<u32,u8>(cmd_byte));
114 }
115
116 // check to see if we have even enough bytes for a complete uleb128
117 size_t payload_len = 0;
118 if (!try_extract_datum_uleb128<size_t>(inbuf, pos, "netcmd payload length", payload_len))
119 return false;
120
121 // they might have given us a bogus size
122 if (payload_len > constants::netcmd_payload_limit)
123 throw bad_decode(F("oversized payload of '%d' bytes") % payload_len);
124
125 // there might not be enough data yet in the input buffer
126 if (inbuf.size() < pos + payload_len + sizeof(u32))
127 return false;
128
129 out.payload = extract_substring(inbuf, pos, payload_len, "netcmd payload");
130
131 // they might have given us bogus data
132 u32 checksum = extract_datum_lsb<u32>(inbuf, pos, "netcmd checksum");
133 adler32 check(reinterpret_cast<u8 const *>(out.payload.data()),
134 out.payload.size());
135 if (checksum != check.sum())
136 throw bad_decode(F("bad checksum 0x%x vs. 0x%x") % checksum % check.sum());
137
138 return true;
139}
140
141////////////////////////////////////////////
142// payload reader/writer functions follow //
143////////////////////////////////////////////
144
145void
146read_error_cmd_payload(std::string const & in,
147 std::string & errmsg)
148{
149 size_t pos = 0;
150 // syntax is: <errmsg:vstr>
151 extract_variable_length_string(in, errmsg, pos, "error netcmd, message");
152 assert_end_of_buffer(in, pos, "error netcmd payload");
153}
154
155void
156write_error_cmd_payload(std::string const & errmsg,
157 std::string & out)
158{
159 insert_variable_length_string(errmsg, out);
160}
161
162
163void
164read_hello_cmd_payload(string const & in,
165 rsa_keypair_id & server_keyname,
166 rsa_pub_key & server_key,
167 id & nonce)
168{
169 size_t pos = 0;
170 // syntax is: <server keyname:vstr> <server pubkey:vstr> <nonce:20 random bytes>
171 string skn_str, sk_str;
172 extract_variable_length_string(in, skn_str, pos, "hello netcmd, server key name");
173 server_keyname = rsa_keypair_id(skn_str);
174 extract_variable_length_string(in, sk_str, pos, "hello netcmd, server key");
175 server_key = rsa_pub_key(sk_str);
176 nonce = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes,
177 "hello netcmd, nonce"));
178 assert_end_of_buffer(in, pos, "hello netcmd payload");
179}
180
181void
182write_hello_cmd_payload(rsa_keypair_id const & server_keyname,
183 rsa_pub_key const & server_key,
184 id const & nonce,
185 string & out)
186{
187 I(nonce().size() == constants::merkle_hash_length_in_bytes);
188 insert_variable_length_string(server_keyname(), out);
189 insert_variable_length_string(server_key(), out);
190 out += nonce();
191}
192
193
194void
195read_anonymous_cmd_payload(std::string const & in,
196 protocol_role & role,
197 std::string & collection,
198 id & nonce2)
199{
200 size_t pos = 0;
201 // syntax is: <role:1 byte> <collection: vstr> <nonce2: 20 random bytes>
202 u8 role_byte = extract_datum_lsb<u8>(in, pos, "anonymous netcmd, role");
203 if (role_byte != static_cast<u8>(source_role)
204 && role_byte != static_cast<u8>(sink_role)
205 && role_byte != static_cast<u8>(source_and_sink_role))
206 throw bad_decode(F("unknown role specifier %d") % widen<u32,u8>(role_byte));
207 role = static_cast<protocol_role>(role_byte);
208 extract_variable_length_string(in, collection, pos, "anonymous netcmd, collection name");
209 nonce2 = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes,
210 "anonymous netcmd, nonce2"));
211 assert_end_of_buffer(in, pos, "anonymous netcmd payload");
212}
213
214void
215write_anonymous_cmd_payload(protocol_role role,
216 std::string const & collection,
217 id const & nonce2,
218 std::string & out)
219{
220 I(nonce2().size() == constants::merkle_hash_length_in_bytes);
221 out += static_cast<char>(role);
222 insert_variable_length_string(collection, out);
223 out += nonce2();
224}
225
226void
227read_auth_cmd_payload(string const & in,
228 protocol_role & role,
229 string & collection,
230 id & client,
231 id & nonce1,
232 id & nonce2,
233 string & signature)
234{
235 size_t pos = 0;
236 // syntax is: <role:1 byte> <collection: vstr>
237 // <client: 20 bytes sha1> <nonce1: 20 random bytes> <nonce2: 20 random bytes>
238 // <signature: vstr>
239 u8 role_byte = extract_datum_lsb<u8>(in, pos, "auth netcmd, role");
240 if (role_byte != static_cast<u8>(source_role)
241 && role_byte != static_cast<u8>(sink_role)
242 && role_byte != static_cast<u8>(source_and_sink_role))
243 throw bad_decode(F("unknown role specifier %d") % widen<u32,u8>(role_byte));
244 role = static_cast<protocol_role>(role_byte);
245 extract_variable_length_string(in, collection, pos, "auth netcmd, collection name");
246 client = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes,
247 "auth netcmd, client identifier"));
248 nonce1 = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes,
249 "auth netcmd, nonce1"));
250 nonce2 = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes,
251 "auth netcmd, nonce2"));
252 extract_variable_length_string(in, signature, pos, "auth netcmd, signature");
253 assert_end_of_buffer(in, pos, "auth netcmd payload");
254}
255
256void
257write_auth_cmd_payload(protocol_role role,
258 string const & collection,
259 id const & client,
260 id const & nonce1,
261 id const & nonce2,
262 string const & signature,
263 string & out)
264{
265 I(client().size() == constants::merkle_hash_length_in_bytes);
266 I(nonce1().size() == constants::merkle_hash_length_in_bytes);
267 I(nonce2().size() == constants::merkle_hash_length_in_bytes);
268 out += static_cast<char>(role);
269 insert_variable_length_string(collection, out);
270 out += client();
271 out += nonce1();
272 out += nonce2();
273 insert_variable_length_string(signature, out);
274}
275
276
277void
278read_confirm_cmd_payload(string const & in,
279 string & signature)
280{
281 size_t pos = 0;
282
283 // syntax is: <signature: vstr>
284 extract_variable_length_string(in, signature, pos, "confirm netcmd, signature");
285 assert_end_of_buffer(in, pos, "confirm netcmd payload");
286}
287
288void
289write_confirm_cmd_payload(string const & signature,
290 string & out)
291{
292 insert_variable_length_string(signature, out);
293}
294
295void
296read_refine_cmd_payload(string const & in, merkle_node & node)
297{
298 // syntax is: <node: a merkle tree node>
299 read_node(in, node);
300}
301
302void
303write_refine_cmd_payload(merkle_node const & node, string & out)
304{
305 write_node(node, out);
306}
307
308void
309read_done_cmd_payload(string const & in,
310 size_t & level,
311 netcmd_item_type & type)
312{
313 size_t pos = 0;
314 // syntax is: <level: uleb128> <type: 1 byte>
315 level = extract_datum_uleb128<size_t>(in, pos, "done netcmd, level number");
316 type = read_netcmd_item_type(in, pos, "done netcmd, item type");
317 assert_end_of_buffer(in, pos, "done netcmd payload");
318}
319
320void
321write_done_cmd_payload(size_t level,
322 netcmd_item_type type,
323 string & out)
324{
325 insert_datum_uleb128<size_t>(level, out);
326 out += static_cast<char>(type);
327}
328
329void
330read_send_data_cmd_payload(string const & in,
331 netcmd_item_type & type,
332 id & item)
333{
334 size_t pos = 0;
335 // syntax is: <type: 1 byte> <id: 20 bytes sha1>
336 type = read_netcmd_item_type(in, pos, "send_data netcmd, item type");
337 item = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes,
338 "send_data netcmd, item identifier"));
339 assert_end_of_buffer(in, pos, "send_data netcmd payload");
340}
341
342void
343write_send_data_cmd_payload(netcmd_item_type type,
344 id const & item,
345 string & out)
346{
347 I(item().size() == constants::merkle_hash_length_in_bytes);
348 out += static_cast<char>(type);
349 out += item();
350}
351
352void
353read_send_delta_cmd_payload(string const & in,
354 netcmd_item_type & type,
355 id & base,
356 id & ident)
357{
358 size_t pos = 0;
359 // syntax is: <type: 1 byte> <src: 20 bytes sha1> <dst: 20 bytes sha1>
360 type = read_netcmd_item_type(in, pos, "send_delta netcmd, item type");
361 base = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes,
362 "send_delta netcmd, base item identifier"));
363 ident = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes,
364 "send_delta netcmd, ident item identifier"));
365 assert_end_of_buffer(in, pos, "send_delta netcmd payload");
366}
367
368void
369write_send_delta_cmd_payload(netcmd_item_type type,
370 id const & base,
371 id const & ident,
372 string & out)
373{
374 I(base().size() == constants::merkle_hash_length_in_bytes);
375 I(ident().size() == constants::merkle_hash_length_in_bytes);
376 out += static_cast<char>(type);
377 out += base();
378 out += ident();
379}
380
381void
382read_data_cmd_payload(string const & in,
383 netcmd_item_type & type,
384 id & item,
385 string & dat)
386{
387 size_t pos = 0;
388 // syntax is: <type: 1 byte> <id: 20 bytes sha1>
389 // <compressed_p1: 1 byte> <dat: vstr>
390
391 type = read_netcmd_item_type(in, pos, "data netcmd, item type");
392 item = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes,
393 "data netcmd, item identifier"));
394
395 dat.clear();
396 u8 compressed_p = extract_datum_lsb<u8>(in, pos, "data netcmd, compression flag");
397 extract_variable_length_string(in, dat, pos, "data netcmd, data payload");
398 if (compressed_p == 1)
399 dat = xform<CryptoPP::Gunzip>(dat);
400 assert_end_of_buffer(in, pos, "data netcmd payload");
401}
402
403void
404write_data_cmd_payload(netcmd_item_type type,
405 id const & item,
406 string const & dat,
407 string & out)
408{
409 I(item().size() == constants::merkle_hash_length_in_bytes);
410 out += static_cast<char>(type);
411 out += item();
412 if (dat.size() > constants::netcmd_minimum_bytes_to_bother_with_gzip)
413 {
414 string tmp;
415 tmp = xform<CryptoPP::Gzip>(dat);
416 out += static_cast<char>(1); // compressed flag
417 insert_variable_length_string(tmp, out);
418 }
419 else
420 {
421 out += static_cast<char>(0); // compressed flag
422 insert_variable_length_string(dat, out);
423 }
424}
425
426
427void
428read_delta_cmd_payload(string const & in,
429 netcmd_item_type & type,
430 id & base, id & ident, delta & del)
431{
432 size_t pos = 0;
433 // syntax is: <type: 1 byte> <src: 20 bytes sha1> <dst: 20 bytes sha1>
434 // <compressed_p: 1 byte> <del: vstr>
435 type = read_netcmd_item_type(in, pos, "delta netcmd, item type");
436 base = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes,
437 "delta netcmd, base identifier"));
438 ident = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes,
439 "delta netcmd, ident identifier"));
440 u8 compressed_p = extract_datum_lsb<u8>(in, pos, "delta netcmd, compression flag");
441 string tmp;
442 extract_variable_length_string(in, tmp, pos, "delta netcmd, delta payload");
443 if (compressed_p == 1)
444 tmp = xform<CryptoPP::Gunzip>(tmp);
445 del = delta(tmp);
446 assert_end_of_buffer(in, pos, "delta netcmd payload");
447}
448
449void
450write_delta_cmd_payload(netcmd_item_type & type,
451 id const & base, id const & ident,
452 delta const & del, string & out)
453{
454 I(base().size() == constants::merkle_hash_length_in_bytes);
455 I(ident().size() == constants::merkle_hash_length_in_bytes);
456 out += static_cast<char>(type);
457 out += base();
458 out += ident();
459
460 string tmp = del();
461
462 if (tmp.size() > constants::netcmd_minimum_bytes_to_bother_with_gzip)
463 {
464 out += static_cast<char>(1); // compressed flag
465 tmp = xform<CryptoPP::Gzip>(tmp);
466 }
467 else
468 {
469 out += static_cast<char>(0); // compressed flag
470 }
471 I(tmp.size() <= constants::netcmd_payload_limit);
472 insert_variable_length_string(tmp, out);
473}
474
475
476void
477read_nonexistant_cmd_payload(string const & in,
478 netcmd_item_type & type,
479 id & item)
480{
481 size_t pos = 0;
482 // syntax is: <type: 1 byte> <id: 20 bytes sha1>
483 type = read_netcmd_item_type(in, pos, "nonexistant netcmd, item type");
484 item = id(extract_substring(in, pos, constants::merkle_hash_length_in_bytes,
485 "nonexistant netcmd, item identifier"));
486 assert_end_of_buffer(in, pos, "nonexistant netcmd payload");
487}
488
489void
490write_nonexistant_cmd_payload(netcmd_item_type type,
491 id const & item,
492 string & out)
493{
494 I(item().size() == constants::merkle_hash_length_in_bytes);
495 out += static_cast<char>(type);
496 out += item();
497}
498
499
500#ifdef BUILD_UNIT_TESTS
501
502#include "unit_tests.hh"
503#include "transforms.hh"
504#include <boost/lexical_cast.hpp>
505
506void
507test_netcmd_functions()
508{
509
510 try
511 {
512
513 // error_cmd
514 {
515 L(F("checking i/o round trip on error_cmd\n"));
516 netcmd out_cmd, in_cmd;
517 string out_errmsg("your shoelaces are untied"), in_errmsg;
518 string buf;
519 out_cmd.cmd_code = error_cmd;
520 write_error_cmd_payload(out_errmsg, out_cmd.payload);
521 write_netcmd(out_cmd, buf);
522 BOOST_CHECK(read_netcmd(buf, in_cmd));
523 read_error_cmd_payload(in_cmd.payload, in_errmsg);
524 BOOST_CHECK(in_cmd == out_cmd);
525 BOOST_CHECK(in_errmsg == out_errmsg);
526 L(F("errmsg_cmd test done, buffer was %d bytes\n") % buf.size());
527 }
528
529 // bye_cmd
530 {
531 L(F("checking i/o round trip on bye_cmd\n"));
532 netcmd out_cmd, in_cmd;
533 string buf;
534 out_cmd.cmd_code = bye_cmd;
535 write_netcmd(out_cmd, buf);
536 BOOST_CHECK(read_netcmd(buf, in_cmd));
537 BOOST_CHECK(in_cmd == out_cmd);
538 L(F("bye_cmd test done, buffer was %d bytes\n") % buf.size());
539 }
540
541 // hello_cmd
542 {
543 L(F("checking i/o round trip on hello_cmd\n"));
544 netcmd out_cmd, in_cmd;
545 string buf;
546 rsa_keypair_id out_server_keyname("server@there"), in_server_keyname;
547 rsa_pub_key out_server_key("9387938749238792874"), in_server_key;
548 id out_nonce(raw_sha1("nonce it up")), in_nonce;
549 out_cmd.cmd_code = hello_cmd;
550 write_hello_cmd_payload(out_server_keyname, out_server_key, out_nonce, out_cmd.payload);
551 write_netcmd(out_cmd, buf);
552 BOOST_CHECK(read_netcmd(buf, in_cmd));
553 read_hello_cmd_payload(in_cmd.payload, in_server_keyname, in_server_key, in_nonce);
554 BOOST_CHECK(in_cmd == out_cmd);
555 BOOST_CHECK(in_server_keyname == out_server_keyname);
556 BOOST_CHECK(in_server_key == out_server_key);
557 BOOST_CHECK(in_nonce == out_nonce);
558 L(F("hello_cmd test done, buffer was %d bytes\n") % buf.size());
559 }
560
561 // anonymous_cmd
562 {
563 L(F("checking i/o round trip on anonymous_cmd\n"));
564 netcmd out_cmd, in_cmd;
565 protocol_role out_role = source_and_sink_role, in_role;
566 string buf;
567 id out_nonce2(raw_sha1("nonce start my heart")), in_nonce2;
568 string out_collection("radishes galore!"), in_collection;
569
570 out_cmd.cmd_code = anonymous_cmd;
571 write_anonymous_cmd_payload(out_role, out_collection, out_nonce2, out_cmd.payload);
572 write_netcmd(out_cmd, buf);
573 BOOST_CHECK(read_netcmd(buf, in_cmd));
574 read_anonymous_cmd_payload(in_cmd.payload, in_role, in_collection, in_nonce2);
575 BOOST_CHECK(in_cmd == out_cmd);
576 BOOST_CHECK(in_nonce2 == out_nonce2);
577 BOOST_CHECK(in_role == out_role);
578 L(F("anonymous_cmd test done, buffer was %d bytes\n") % buf.size());
579 }
580
581 // auth_cmd
582 {
583 L(F("checking i/o round trip on auth_cmd\n"));
584 netcmd out_cmd, in_cmd;
585 protocol_role out_role = source_and_sink_role, in_role;
586 string buf;
587 id out_client(raw_sha1("happy client day")), out_nonce1(raw_sha1("nonce me amadeus")),
588 out_nonce2(raw_sha1("nonce start my heart")),
589 in_client, in_nonce1, in_nonce2;
590 string out_signature(raw_sha1("burble") + raw_sha1("gorby")), out_collection("radishes galore!"),
591 in_signature, in_collection;
592
593 out_cmd.cmd_code = auth_cmd;
594 write_auth_cmd_payload(out_role, out_collection, out_client, out_nonce1,
595 out_nonce2, out_signature, out_cmd.payload);
596 write_netcmd(out_cmd, buf);
597 BOOST_CHECK(read_netcmd(buf, in_cmd));
598 read_auth_cmd_payload(in_cmd.payload, in_role, in_collection, in_client,
599 in_nonce1, in_nonce2, in_signature);
600 BOOST_CHECK(in_cmd == out_cmd);
601 BOOST_CHECK(in_client == out_client);
602 BOOST_CHECK(in_nonce1 == out_nonce1);
603 BOOST_CHECK(in_nonce2 == out_nonce2);
604 BOOST_CHECK(in_signature == out_signature);
605 BOOST_CHECK(in_role == out_role);
606 L(F("auth_cmd test done, buffer was %d bytes\n") % buf.size());
607 }
608
609 // confirm_cmd
610 {
611 L(F("checking i/o round trip on confirm_cmd\n"));
612 netcmd out_cmd, in_cmd;
613 string buf;
614 string out_signature(raw_sha1("egg") + raw_sha1("tomago")), in_signature;
615
616 out_cmd.cmd_code = confirm_cmd;
617 write_confirm_cmd_payload(out_signature, out_cmd.payload);
618 write_netcmd(out_cmd, buf);
619 BOOST_CHECK(read_netcmd(buf, in_cmd));
620 read_confirm_cmd_payload(in_cmd.payload, in_signature);
621 BOOST_CHECK(in_cmd == out_cmd);
622 BOOST_CHECK(in_signature == out_signature);
623 L(F("confirm_cmd test done, buffer was %d bytes\n") % buf.size());
624 }
625
626 // refine_cmd
627 {
628 L(F("checking i/o round trip on refine_cmd\n"));
629 netcmd out_cmd, in_cmd;
630 string buf;
631 merkle_node out_node, in_node;
632
633 out_node.set_raw_slot(0, id(raw_sha1("The police pulled Kris Kringle over")));
634 out_node.set_raw_slot(3, id(raw_sha1("Kris Kringle tried to escape from the police")));
635 out_node.set_raw_slot(8, id(raw_sha1("He was arrested for auto theft")));
636 out_node.set_raw_slot(15, id(raw_sha1("He was whisked away to jail")));
637 out_node.set_slot_state(0, subtree_state);
638 out_node.set_slot_state(3, live_leaf_state);
639 out_node.set_slot_state(8, dead_leaf_state);
640 out_node.set_slot_state(15, subtree_state);
641
642 out_cmd.cmd_code = refine_cmd;
643 write_refine_cmd_payload(out_node, out_cmd.payload);
644 write_netcmd(out_cmd, buf);
645 BOOST_CHECK(read_netcmd(buf, in_cmd));
646 read_refine_cmd_payload(in_cmd.payload, in_node);
647 BOOST_CHECK(in_cmd == out_cmd);
648 BOOST_CHECK(in_node == out_node);
649 L(F("refine_cmd test done, buffer was %d bytes\n") % buf.size());
650 }
651
652 // done_cmd
653 {
654 L(F("checking i/o round trip on done_cmd\n"));
655 netcmd out_cmd, in_cmd;
656 size_t out_level(12), in_level;
657 netcmd_item_type out_type(key_item), in_type(manifest_item);
658 string buf;
659
660 out_cmd.cmd_code = done_cmd;
661 write_done_cmd_payload(out_level, out_type, out_cmd.payload);
662 write_netcmd(out_cmd, buf);
663 BOOST_CHECK(read_netcmd(buf, in_cmd));
664 read_done_cmd_payload(in_cmd.payload, in_level, in_type);
665 BOOST_CHECK(in_level == out_level);
666 BOOST_CHECK(in_type == out_type);
667 L(F("done_cmd test done, buffer was %d bytes\n") % buf.size());
668 }
669
670 // send_data_cmd
671 {
672 L(F("checking i/o round trip on send_data_cmd\n"));
673 netcmd out_cmd, in_cmd;
674 netcmd_item_type out_type(file_item), in_type(key_item);
675 id out_id(raw_sha1("avocado is the yummiest")), in_id;
676 string buf;
677
678 out_cmd.cmd_code = send_data_cmd;
679 write_send_data_cmd_payload(out_type, out_id, out_cmd.payload);
680 write_netcmd(out_cmd, buf);
681 BOOST_CHECK(read_netcmd(buf, in_cmd));
682 read_send_data_cmd_payload(in_cmd.payload, in_type, in_id);
683 BOOST_CHECK(in_type == out_type);
684 BOOST_CHECK(in_id == out_id);
685 L(F("send_data_cmd test done, buffer was %d bytes\n") % buf.size());
686 }
687
688 // send_delta_cmd
689 {
690 L(F("checking i/o round trip on send_delta_cmd\n"));
691 netcmd out_cmd, in_cmd;
692 netcmd_item_type out_type(file_item), in_type(key_item);
693 id out_head(raw_sha1("when you board an airplane")), in_head;
694 id out_base(raw_sha1("always check the exit locations")), in_base;
695 string buf;
696
697 out_cmd.cmd_code = send_delta_cmd;
698 write_send_delta_cmd_payload(out_type, out_head, out_base, out_cmd.payload);
699 write_netcmd(out_cmd, buf);
700 BOOST_CHECK(read_netcmd(buf, in_cmd));
701 read_send_delta_cmd_payload(in_cmd.payload, in_type, in_head, in_base);
702 BOOST_CHECK(in_type == out_type);
703 BOOST_CHECK(in_head == out_head);
704 BOOST_CHECK(in_base == out_base);
705 L(F("send_delta_cmd test done, buffer was %d bytes\n") % buf.size());
706 }
707
708 // data_cmd
709 {
710 L(F("checking i/o round trip on data_cmd\n"));
711 netcmd out_cmd, in_cmd;
712 netcmd_item_type out_type(file_item), in_type(key_item);
713 id out_id(raw_sha1("tuna is not yummy")), in_id;
714 string out_dat("thank you for flying northwest"), in_dat;
715 string buf;
716 out_cmd.cmd_code = data_cmd;
717 write_data_cmd_payload(out_type, out_id, out_dat, out_cmd.payload);
718 write_netcmd(out_cmd, buf);
719 BOOST_CHECK(read_netcmd(buf, in_cmd));
720 read_data_cmd_payload(in_cmd.payload, in_type, in_id, in_dat);
721 BOOST_CHECK(in_id == out_id);
722 BOOST_CHECK(in_dat == out_dat);
723 L(F("data_cmd test done, buffer was %d bytes\n") % buf.size());
724 }
725
726 // delta_cmd
727 {
728 L(F("checking i/o round trip on delta_cmd\n"));
729 netcmd out_cmd, in_cmd;
730 netcmd_item_type out_type(file_item), in_type(key_item);
731 id out_head(raw_sha1("your seat cusion can be reused")), in_head;
732 id out_base(raw_sha1("as a floatation device")), in_base;
733 delta out_delta("goodness, this is not an xdelta"), in_delta;
734 string buf;
735
736 out_cmd.cmd_code = delta_cmd;
737 write_delta_cmd_payload(out_type, out_head, out_base, out_delta, out_cmd.payload);
738 write_netcmd(out_cmd, buf);
739 BOOST_CHECK(read_netcmd(buf, in_cmd));
740 read_delta_cmd_payload(in_cmd.payload, in_type, in_head, in_base, in_delta);
741 BOOST_CHECK(in_type == out_type);
742 BOOST_CHECK(in_head == out_head);
743 BOOST_CHECK(in_base == out_base);
744 BOOST_CHECK(in_delta == out_delta);
745 L(F("delta_cmd test done, buffer was %d bytes\n") % buf.size());
746 }
747
748 // nonexistant_cmd
749 {
750 L(F("checking i/o round trip on nonexistant_cmd\n"));
751 netcmd out_cmd, in_cmd;
752 netcmd_item_type out_type(file_item), in_type(key_item);
753 id out_id(raw_sha1("avocado is the yummiest")), in_id;
754 string buf;
755
756 out_cmd.cmd_code = nonexistant_cmd;
757 write_send_data_cmd_payload(out_type, out_id, out_cmd.payload);
758 write_netcmd(out_cmd, buf);
759 BOOST_CHECK(read_netcmd(buf, in_cmd));
760 read_send_data_cmd_payload(in_cmd.payload, in_type, in_id);
761 BOOST_CHECK(in_type == out_type);
762 BOOST_CHECK(in_id == out_id);
763 L(F("nonexistant_cmd test done, buffer was %d bytes\n") % buf.size());
764 }
765
766 }
767 catch (bad_decode & d)
768 {
769 L(F("bad decode exception: '%s'\n") % d.what);
770 throw;
771 }
772}
773
774void
775add_netcmd_tests(test_suite * suite)
776{
777 suite->add(BOOST_TEST_CASE(&test_netcmd_functions));
778}
779
780#endif // BUILD_UNIT_TESTS

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status