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

Archive Download this file

Branches

Tags

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