monotone

monotone Mtn Source Tree

Root/src/netcmd.cc

1// Copyright (C) 2004 Graydon Hoare <graydon@pobox.com>
2//
3// This program is made available under the GNU GPL version 2.0 or
4// greater. See the accompanying file COPYING for details.
5//
6// This program is distributed WITHOUT ANY WARRANTY; without even the
7// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8// PURPOSE.
9
10#include "base.hh"
11#include "vector.hh"
12#include <utility>
13
14#include "constants.hh"
15#include "netcmd.hh"
16#include "netio.hh"
17#include "numeric_vocab.hh"
18#include "sanity.hh"
19#include "transforms.hh"
20#include "hmac.hh"
21#include "globish.hh"
22
23using std::pair;
24using std::string;
25using std::vector;
26
27static netcmd_item_type
28read_netcmd_item_type(string const & in,
29 size_t & pos,
30 string const & name)
31{
32 u8 tmp = extract_datum_lsb<u8>(in, pos, name);
33 switch (tmp)
34 {
35 case static_cast<u8>(revision_item):
36 return revision_item;
37 case static_cast<u8>(file_item):
38 return file_item;
39 case static_cast<u8>(cert_item):
40 return cert_item;
41 case static_cast<u8>(key_item):
42 return key_item;
43 case static_cast<u8>(epoch_item):
44 return epoch_item;
45 default:
46 throw bad_decode(F("unknown item type 0x%x for '%s'")
47 % static_cast<int>(tmp) % name);
48 }
49}
50
51netcmd::netcmd(u8 ver)
52 : version(ver),
53 cmd_code(error_cmd)
54{}
55
56size_t netcmd::encoded_size() const
57{
58 string tmp;
59 insert_datum_uleb128<size_t>(payload.size(), tmp);
60 return 1 // netsync version
61 + 1 // command code
62 + tmp.size() + payload.size() // payload as vstring
63 + constants::netsync_hmac_value_length_in_bytes; // hmac
64}
65
66bool
67netcmd::operator==(netcmd const & other) const
68{
69 return version == other.version &&
70 cmd_code == other.cmd_code &&
71 payload == other.payload;
72}
73
74// note: usher_reply_cmd does not get included in the hmac.
75void
76netcmd::write(string & out, chained_hmac & hmac) const
77{
78 size_t oldlen = out.size();
79 out += static_cast<char>(version);
80 out += static_cast<char>(cmd_code);
81 insert_variable_length_string(payload, out);
82
83 if (hmac.is_active() && cmd_code != usher_reply_cmd && cmd_code != usher_cmd)
84 {
85 string digest = hmac.process(out, oldlen);
86 I(hmac.hmac_length == constants::netsync_hmac_value_length_in_bytes);
87 out.append(digest);
88 }
89}
90
91// note: usher_cmd does not get included in the hmac.
92bool
93netcmd::read(u8 min_version, u8 max_version,
94 string_queue & inbuf, chained_hmac & hmac)
95{
96 size_t pos = 0;
97
98 if (inbuf.size() < constants::netcmd_minsz)
99 return false;
100
101 u8 extracted_ver = extract_datum_lsb<u8>(inbuf, pos, "netcmd protocol number");
102 bool too_old = extracted_ver < min_version;
103 bool too_new = extracted_ver > max_version;
104
105 u8 cmd_byte = extract_datum_lsb<u8>(inbuf, pos, "netcmd code");
106 switch (cmd_byte)
107 {
108 case static_cast<u8>(hello_cmd):
109 case static_cast<u8>(bye_cmd):
110 case static_cast<u8>(anonymous_cmd):
111 case static_cast<u8>(auth_cmd):
112 case static_cast<u8>(error_cmd):
113 case static_cast<u8>(confirm_cmd):
114 case static_cast<u8>(refine_cmd):
115 case static_cast<u8>(done_cmd):
116 case static_cast<u8>(data_cmd):
117 case static_cast<u8>(delta_cmd):
118 case static_cast<u8>(automate_cmd):
119 case static_cast<u8>(automate_headers_request_cmd):
120 case static_cast<u8>(automate_headers_reply_cmd):
121 case static_cast<u8>(automate_command_cmd):
122 case static_cast<u8>(automate_packet_cmd):
123 case static_cast<u8>(usher_cmd):
124 case static_cast<u8>(usher_reply_cmd):
125 cmd_code = static_cast<netcmd_code>(cmd_byte);
126 break;
127 default:
128 // if the versions don't match, we will throw the more descriptive
129 // error immediately after this switch.
130 if (!too_old && !too_new)
131 throw bad_decode(F("unknown netcmd code 0x%x")
132 % widen<u32,u8>(cmd_byte));
133 }
134 // check that the version is reasonable
135 if (cmd_code != usher_cmd)
136 {
137 if (too_old || (cmd_code != usher_reply_cmd && too_new))
138 {
139 throw bad_decode(F("protocol version mismatch: wanted between '%d' and '%d' got '%d' (netcmd code %d)\n"
140 "%s")
141 % widen<u32,u8>(min_version)
142 % widen<u32,u8>(max_version)
143 % widen<u32,u8>(extracted_ver)
144 % widen<u32,u8>(cmd_code)
145 % ((max_version < extracted_ver)
146 ? _("the remote side has a newer, incompatible version of monotone")
147 : _("the remote side has an older, incompatible version of monotone")));
148 }
149 }
150 version = extracted_ver;
151
152 // check to see if we have even enough bytes for a complete uleb128
153 size_t payload_len = 0;
154 if (!try_extract_datum_uleb128<size_t>(inbuf, pos, "netcmd payload length",
155 payload_len))
156 return false;
157
158 // they might have given us a bogus size
159 if (payload_len > constants::netcmd_payload_limit)
160 throw bad_decode(F("oversized payload of '%d' bytes") % payload_len);
161
162 // there might not be enough data yet in the input buffer
163 unsigned int minsize;
164 if (hmac.is_active() && cmd_code != usher_cmd && cmd_code != usher_reply_cmd)
165 minsize = pos + payload_len + constants::netsync_hmac_value_length_in_bytes;
166 else
167 minsize = pos + payload_len;
168
169 if (inbuf.size() < minsize)
170 {
171 return false;
172 }
173
174 string digest;
175 string cmd_digest;
176
177 if (hmac.is_active() && cmd_code != usher_cmd && cmd_code != usher_reply_cmd)
178 {
179 // grab it before the data gets munged
180 I(hmac.hmac_length == constants::netsync_hmac_value_length_in_bytes);
181 digest = hmac.process(inbuf, 0, pos + payload_len);
182 }
183
184 payload = extract_substring(inbuf, pos, payload_len, "netcmd payload");
185
186 if (hmac.is_active() && cmd_code != usher_cmd && cmd_code != usher_reply_cmd)
187 {
188 // they might have given us bogus data
189 cmd_digest = extract_substring(inbuf, pos,
190 constants::netsync_hmac_value_length_in_bytes,
191 "netcmd HMAC");
192 }
193
194 inbuf.pop_front(pos);
195
196 if (hmac.is_active()
197 && cmd_code != usher_cmd && cmd_code != usher_reply_cmd
198 && cmd_digest != digest)
199 {
200 throw bad_decode(F("bad HMAC checksum (got %s, wanted %s)\n"
201 "this suggests data was corrupted in transit")
202 % encode_hexenc(cmd_digest, origin::network)
203 % encode_hexenc(digest, origin::network));
204 }
205
206 L(FL("read packet with code %d and version %d")
207 % widen<u32>(cmd_code) % widen<u32>(version));
208
209 return true;
210}
211
212////////////////////////////////////////////
213// payload reader/writer functions follow //
214////////////////////////////////////////////
215
216void
217netcmd::read_error_cmd(string & errmsg) const
218{
219 size_t pos = 0;
220 // syntax is: <errmsg:vstr>
221 extract_variable_length_string(payload, errmsg, pos, "error netcmd, message");
222 assert_end_of_buffer(payload, pos, "error netcmd payload");
223}
224
225void
226netcmd::write_error_cmd(string const & errmsg)
227{
228 cmd_code = error_cmd;
229 payload.clear();
230 insert_variable_length_string(errmsg, payload);
231}
232
233
234void
235netcmd::read_hello_cmd(u8 & server_version,
236 key_name & server_keyname,
237 rsa_pub_key & server_key,
238 id & nonce) const
239{
240 server_version = version;
241 size_t pos = 0;
242 // syntax is: <server keyname:vstr> <server pubkey:vstr> <nonce:20 random bytes>
243 string skn_str, sk_str;
244 extract_variable_length_string(payload, skn_str, pos,
245 "hello netcmd, server key name");
246 server_keyname = key_name(skn_str, origin::network);
247 extract_variable_length_string(payload, sk_str, pos,
248 "hello netcmd, server key");
249 server_key = rsa_pub_key(sk_str, origin::network);
250 nonce = id(extract_substring(payload, pos,
251 constants::merkle_hash_length_in_bytes,
252 "hello netcmd, nonce"), origin::network);
253 assert_end_of_buffer(payload, pos, "hello netcmd payload");
254}
255
256void
257netcmd::write_hello_cmd(key_name const & server_keyname,
258 rsa_pub_key const & server_key,
259 id const & nonce)
260{
261 cmd_code = hello_cmd;
262 payload.clear();
263 I(nonce().size() == constants::merkle_hash_length_in_bytes);
264 insert_variable_length_string(server_keyname(), payload);
265 insert_variable_length_string(server_key(), payload);
266 payload += nonce();
267}
268
269
270void
271netcmd::read_bye_cmd(u8 & phase) const
272{
273 size_t pos = 0;
274 // syntax is: <phase: 1 byte>
275 phase = extract_datum_lsb<u8>(payload, pos, "bye netcmd, phase number");
276 assert_end_of_buffer(payload, pos, "bye netcmd payload");
277}
278
279
280void
281netcmd::write_bye_cmd(u8 phase)
282{
283 cmd_code = bye_cmd;
284 payload.clear();
285 payload += phase;
286}
287
288
289void
290netcmd::read_anonymous_cmd(protocol_role & role,
291 globish & include_pattern,
292 globish & exclude_pattern,
293 rsa_oaep_sha_data & hmac_key_encrypted) const
294{
295 size_t pos = 0;
296 // syntax is: <role:1 byte> <include_pattern: vstr> <exclude_pattern: vstr> <hmac_key_encrypted: vstr>
297 u8 role_byte = extract_datum_lsb<u8>(payload, pos, "anonymous(hmac) netcmd, role");
298 if (role_byte != static_cast<u8>(source_role)
299 && role_byte != static_cast<u8>(sink_role)
300 && role_byte != static_cast<u8>(source_and_sink_role))
301 throw bad_decode(F("unknown role specifier %d") % widen<u32,u8>(role_byte));
302 role = static_cast<protocol_role>(role_byte);
303 string pattern_string;
304 extract_variable_length_string(payload, pattern_string, pos,
305 "anonymous(hmac) netcmd, include_pattern");
306 include_pattern = globish(pattern_string, origin::network);
307 extract_variable_length_string(payload, pattern_string, pos,
308 "anonymous(hmac) netcmd, exclude_pattern");
309 exclude_pattern = globish(pattern_string, origin::network);
310 string hmac_key_string;
311 extract_variable_length_string(payload, hmac_key_string, pos,
312 "anonymous(hmac) netcmd, hmac_key_encrypted");
313 hmac_key_encrypted = rsa_oaep_sha_data(hmac_key_string, origin::network);
314 assert_end_of_buffer(payload, pos, "anonymous(hmac) netcmd payload");
315}
316
317void
318netcmd::write_anonymous_cmd(protocol_role role,
319 globish const & include_pattern,
320 globish const & exclude_pattern,
321 rsa_oaep_sha_data const & hmac_key_encrypted)
322{
323 cmd_code = anonymous_cmd;
324 payload += static_cast<char>(role);
325 insert_variable_length_string(include_pattern(), payload);
326 insert_variable_length_string(exclude_pattern(), payload);
327 insert_variable_length_string(hmac_key_encrypted(), payload);
328}
329
330void
331netcmd::read_auth_cmd(protocol_role & role,
332 globish & include_pattern,
333 globish & exclude_pattern,
334 key_id & client,
335 id & nonce1,
336 rsa_oaep_sha_data & hmac_key_encrypted,
337 rsa_sha1_signature & signature) const
338{
339 size_t pos = 0;
340 // syntax is: <role:1 byte> <include_pattern: vstr> <exclude_pattern: vstr>
341 // <client: 20 bytes sha1> <nonce1: 20 random bytes>
342 // <hmac_key_encrypted: vstr> <signature: vstr>
343 u8 role_byte = extract_datum_lsb<u8>(payload, pos, "auth netcmd, role");
344 if (role_byte != static_cast<u8>(source_role)
345 && role_byte != static_cast<u8>(sink_role)
346 && role_byte != static_cast<u8>(source_and_sink_role))
347 throw bad_decode(F("unknown role specifier %d") % widen<u32,u8>(role_byte));
348 role = static_cast<protocol_role>(role_byte);
349 string pattern_string;
350 extract_variable_length_string(payload, pattern_string, pos,
351 "auth(hmac) netcmd, include_pattern");
352 include_pattern = globish(pattern_string, origin::network);
353 extract_variable_length_string(payload, pattern_string, pos,
354 "auth(hmac) netcmd, exclude_pattern");
355 exclude_pattern = globish(pattern_string, origin::network);
356 client = key_id(extract_substring(payload, pos,
357 constants::merkle_hash_length_in_bytes,
358 "auth(hmac) netcmd, client identifier"),
359 origin::network);
360 nonce1 = id(extract_substring(payload, pos,
361 constants::merkle_hash_length_in_bytes,
362 "auth(hmac) netcmd, nonce1"),
363 origin::network);
364 string hmac_key;
365 extract_variable_length_string(payload, hmac_key, pos,
366 "auth(hmac) netcmd, hmac_key_encrypted");
367 hmac_key_encrypted = rsa_oaep_sha_data(hmac_key, origin::network);
368 string sig_string;
369 extract_variable_length_string(payload, sig_string, pos,
370 "auth(hmac) netcmd, signature");
371 signature = rsa_sha1_signature(sig_string, origin::network);
372 assert_end_of_buffer(payload, pos, "auth(hmac) netcmd payload");
373}
374
375void
376netcmd::write_auth_cmd(protocol_role role,
377 globish const & include_pattern,
378 globish const & exclude_pattern,
379 key_id const & client,
380 id const & nonce1,
381 rsa_oaep_sha_data const & hmac_key_encrypted,
382 rsa_sha1_signature const & signature)
383{
384 cmd_code = auth_cmd;
385 I(client.inner()().size() == constants::merkle_hash_length_in_bytes);
386 I(nonce1().size() == constants::merkle_hash_length_in_bytes);
387 payload += static_cast<char>(role);
388 insert_variable_length_string(include_pattern(), payload);
389 insert_variable_length_string(exclude_pattern(), payload);
390 payload += client.inner()();
391 payload += nonce1();
392 insert_variable_length_string(hmac_key_encrypted(), payload);
393 insert_variable_length_string(signature(), payload);
394}
395
396void
397netcmd::read_confirm_cmd() const
398{
399 size_t pos = 0;
400 assert_end_of_buffer(payload, pos, "confirm netcmd payload");
401}
402
403void
404netcmd::write_confirm_cmd()
405{
406 cmd_code = confirm_cmd;
407 payload.clear();
408}
409
410void
411netcmd::read_refine_cmd(refinement_type & ty, merkle_node & node) const
412{
413 // syntax is: <u8: refinement type> <node: a merkle tree node>
414 size_t pos = 0;
415 ty = static_cast<refinement_type>
416 (extract_datum_lsb<u8>
417 (payload, pos,
418 "refine netcmd, refinement type"));
419 read_node(payload, pos, node);
420 assert_end_of_buffer(payload, pos, "refine cmd");
421}
422
423void
424netcmd::write_refine_cmd(refinement_type ty, merkle_node const & node)
425{
426 cmd_code = refine_cmd;
427 payload.clear();
428 payload += static_cast<char>(ty);
429 write_node(node, payload);
430}
431
432void
433netcmd::read_done_cmd(netcmd_item_type & type, size_t & n_items) const
434{
435 size_t pos = 0;
436 // syntax is: <type: 1 byte> <n_items: uleb128>
437 type = read_netcmd_item_type(payload, pos, "done netcmd, item type");
438 n_items = extract_datum_uleb128<size_t>(payload, pos,
439 "done netcmd, item-to-send count");
440 assert_end_of_buffer(payload, pos, "done netcmd payload");
441}
442
443void
444netcmd::write_done_cmd(netcmd_item_type type,
445 size_t n_items)
446{
447 cmd_code = done_cmd;
448 payload.clear();
449 payload += static_cast<char>(type);
450 insert_datum_uleb128<size_t>(n_items, payload);
451}
452
453void
454netcmd::read_data_cmd(netcmd_item_type & type,
455 id & item, string & dat) const
456{
457 size_t pos = 0;
458 // syntax is: <type: 1 byte> <id: 20 bytes sha1>
459 // <compressed_p1: 1 byte> <dat: vstr>
460
461 type = read_netcmd_item_type(payload, pos, "data netcmd, item type");
462 item = id(extract_substring(payload, pos,
463 constants::merkle_hash_length_in_bytes,
464 "data netcmd, item identifier"),
465 origin::network);
466
467 dat.clear();
468 u8 compressed_p = extract_datum_lsb<u8>(payload, pos,
469 "data netcmd, compression flag");
470 extract_variable_length_string(payload, dat, pos,
471 "data netcmd, data payload");
472 if (compressed_p == 1)
473 {
474 gzip<data> zdat(dat, origin::network);
475 data tdat;
476 decode_gzip(zdat, tdat);
477 dat = tdat();
478 }
479 assert_end_of_buffer(payload, pos, "data netcmd payload");
480}
481
482void
483netcmd::write_data_cmd(netcmd_item_type type,
484 id const & item,
485 string const & dat)
486{
487 cmd_code = data_cmd;
488 I(item().size() == constants::merkle_hash_length_in_bytes);
489 payload += static_cast<char>(type);
490 payload += item();
491 if (dat.size() > constants::netcmd_minimum_bytes_to_bother_with_gzip)
492 {
493 gzip<data> zdat;
494 encode_gzip(data(dat, origin::internal), zdat);
495 payload += static_cast<char>(1); // compressed flag
496 insert_variable_length_string(zdat(), payload);
497 }
498 else
499 {
500 payload += static_cast<char>(0); // compressed flag
501 insert_variable_length_string(dat, payload);
502 }
503}
504
505
506void
507netcmd::read_delta_cmd(netcmd_item_type & type,
508 id & base, id & ident, delta & del) const
509{
510 size_t pos = 0;
511 // syntax is: <type: 1 byte> <src: 20 bytes sha1> <dst: 20 bytes sha1>
512 // <compressed_p: 1 byte> <del: vstr>
513 type = read_netcmd_item_type(payload, pos, "delta netcmd, item type");
514 base = id(extract_substring(payload, pos,
515 constants::merkle_hash_length_in_bytes,
516 "delta netcmd, base identifier"),
517 origin::network);
518 ident = id(extract_substring(payload, pos,
519 constants::merkle_hash_length_in_bytes,
520 "delta netcmd, ident identifier"),
521 origin::network);
522 u8 compressed_p = extract_datum_lsb<u8>(payload, pos,
523 "delta netcmd, compression flag");
524 string tmp;
525 extract_variable_length_string(payload, tmp, pos,
526 "delta netcmd, delta payload");
527 if (compressed_p == 1)
528 {
529 gzip<delta> zdel(tmp, origin::network);
530 decode_gzip(zdel, del);
531 }
532 else
533 {
534 del = delta(tmp, origin::network);
535 }
536 assert_end_of_buffer(payload, pos, "delta netcmd payload");
537}
538
539void
540netcmd::write_delta_cmd(netcmd_item_type & type,
541 id const & base, id const & ident,
542 delta const & del)
543{
544 cmd_code = delta_cmd;
545 I(base().size() == constants::merkle_hash_length_in_bytes);
546 I(ident().size() == constants::merkle_hash_length_in_bytes);
547 payload += static_cast<char>(type);
548 payload += base();
549 payload += ident();
550
551 string tmp;
552
553 if (del().size() > constants::netcmd_minimum_bytes_to_bother_with_gzip)
554 {
555 payload += static_cast<char>(1); // compressed flag
556 gzip<delta> zdel;
557 encode_gzip(del, zdel);
558 tmp = zdel();
559 }
560 else
561 {
562 payload += static_cast<char>(0); // compressed flag
563 tmp = del();
564 }
565 I(tmp.size() <= constants::netcmd_payload_limit);
566 insert_variable_length_string(tmp, payload);
567}
568
569void
570netcmd::read_automate_cmd(key_id & client,
571 id & nonce1,
572 rsa_oaep_sha_data & hmac_key_encrypted,
573 rsa_sha1_signature & signature) const
574{
575 size_t pos = 0;
576 client = key_id(extract_substring(payload, pos,
577 constants::merkle_hash_length_in_bytes,
578 "automate netcmd, key id"),
579 origin::network);
580 nonce1 = id(extract_substring(payload, pos,
581 constants::merkle_hash_length_in_bytes,
582 "automate netcmd, nonce1"),
583 origin::network);
584 {
585 string hmac_key;
586 extract_variable_length_string(payload, hmac_key, pos,
587 "automate netcmd, hmac_key_encrypted");
588 hmac_key_encrypted = rsa_oaep_sha_data(hmac_key, origin::network);
589 }
590 {
591 string sig;
592 extract_variable_length_string(payload, sig, pos,
593 "automate netcmd, signature");
594 signature = rsa_sha1_signature(sig, origin::network);
595 }
596 assert_end_of_buffer(payload, pos, "automate netcmd payload");
597}
598
599void
600netcmd::write_automate_cmd(key_id const & client,
601 id const & nonce1,
602 rsa_oaep_sha_data & hmac_key_encrypted,
603 rsa_sha1_signature & signature)
604{
605 cmd_code = automate_cmd;
606
607 I(client.inner()().empty() ||
608 client.inner()().size() == constants::merkle_hash_length_in_bytes);
609 I(nonce1().size() == constants::merkle_hash_length_in_bytes);
610
611 if (client.inner()().empty())
612 {
613 payload += string(constants::merkle_hash_length_in_bytes, 0);
614 }
615 else
616 {
617 payload += client.inner()();
618 }
619 payload += nonce1();
620
621 insert_variable_length_string(hmac_key_encrypted(), payload);
622 insert_variable_length_string(signature(), payload);
623}
624
625void
626netcmd::read_automate_headers_request_cmd() const
627{
628 size_t pos = 0;
629 assert_end_of_buffer(payload, pos, "read automate headers request netcmd payload");
630}
631
632void
633netcmd::write_automate_headers_request_cmd()
634{
635 cmd_code = automate_headers_request_cmd;
636}
637
638void
639netcmd::read_automate_headers_reply_cmd(vector<pair<string, string> > & headers) const
640{
641 size_t pos = 0;
642 size_t nheaders = extract_datum_uleb128<size_t>(payload, pos,
643 "automate headers reply netcmd, count");
644 headers.clear();
645 for (size_t i = 0; i < nheaders; ++i)
646 {
647 string name;
648 extract_variable_length_string(payload, name, pos,
649 "automate headers reply netcmd, name");
650 string value;
651 extract_variable_length_string(payload, value, pos,
652 "automate headers reply netcmd, value");
653 headers.push_back(make_pair(name, value));
654 }
655 assert_end_of_buffer(payload, pos, "automate headers reply netcmd payload");
656}
657
658void
659netcmd::write_automate_headers_reply_cmd(vector<pair<string, string> > const & headers)
660{
661 cmd_code = automate_headers_reply_cmd;
662
663 insert_datum_uleb128<size_t>(headers.size(), payload);
664 for (vector<pair<string, string> >::const_iterator h = headers.begin();
665 h != headers.end(); ++h)
666 {
667 insert_variable_length_string(h->first, payload);
668 insert_variable_length_string(h->second, payload);
669 }
670}
671
672void
673netcmd::read_automate_command_cmd(vector<string> & args,
674 vector<pair<string, string> > & opts) const
675{
676 size_t pos = 0;
677 {
678 size_t nargs = extract_datum_uleb128<size_t>(payload, pos,
679 "automate_command netcmd, arg count");
680 args.clear();
681 for (size_t i = 0; i < nargs; ++i)
682 {
683 string arg;
684 extract_variable_length_string(payload, arg, pos,
685 "automate_command netcmd, argument");
686 args.push_back(arg);
687 }
688 }
689 {
690 size_t nopts = extract_datum_uleb128<size_t>(payload, pos,
691 "automate_command netcmd, option count");
692 opts.clear();
693 for (size_t i = 0; i < nopts; ++i)
694 {
695 string name;
696 extract_variable_length_string(payload, name, pos,
697 "automate_command netcmd, option name");
698 string value;
699 extract_variable_length_string(payload, value, pos,
700 "automate_command netcmd, option value");
701 opts.push_back(make_pair(name, value));
702 }
703 }
704 assert_end_of_buffer(payload, pos, "automate_command netcmd payload");
705}
706
707void
708netcmd::write_automate_command_cmd(vector<string> const & args,
709 vector<pair<string, string> > const & opts)
710{
711 cmd_code = automate_command_cmd;
712
713 insert_datum_uleb128<size_t>(args.size(), payload);
714 for (vector<string>::const_iterator a = args.begin();
715 a != args.end(); ++a)
716 {
717 insert_variable_length_string(*a, payload);
718 }
719
720 insert_datum_uleb128<size_t>(opts.size(), payload);
721 for (vector<pair<string, string> >::const_iterator o = opts.begin();
722 o != opts.end(); ++o)
723 {
724 insert_variable_length_string(o->first, payload);
725 insert_variable_length_string(o->second, payload);
726 }
727}
728
729void
730netcmd::read_automate_packet_cmd(int & command_num,
731 char & stream,
732 string & packet_data) const
733{
734 size_t pos = 0;
735
736 command_num = int(extract_datum_uleb128<size_t>(payload, pos,
737 "automate_packet netcmd, command_num"));
738 stream = char(extract_datum_uleb128<size_t>(payload, pos,
739 "automate_packet netcmd, stream"));
740 extract_variable_length_string(payload, packet_data, pos,
741 "automate_packet netcmd, packet_data");
742 assert_end_of_buffer(payload, pos, "automate_packet netcmd payload");
743}
744
745void
746netcmd::write_automate_packet_cmd(int command_num,
747 char stream,
748 string const & packet_data)
749{
750 cmd_code = automate_packet_cmd;
751
752 insert_datum_uleb128<size_t>(size_t(command_num), payload);
753 insert_datum_uleb128<size_t>(size_t(stream), payload);
754 insert_variable_length_string(packet_data, payload);
755}
756
757void
758netcmd::read_usher_cmd(utf8 & greeting) const
759{
760 size_t pos = 0;
761 string str;
762 extract_variable_length_string(payload, str, pos, "usher netcmd, message");
763 greeting = utf8(str, origin::network);
764 assert_end_of_buffer(payload, pos, "usher netcmd payload");
765}
766
767void
768netcmd::write_usher_cmd(utf8 const & greeting)
769{
770 version = 0;
771 cmd_code = usher_cmd;
772 insert_variable_length_string(greeting(), payload);
773}
774
775void
776netcmd::read_usher_reply_cmd(u8 & version_out,
777 utf8 & server, string & pattern) const
778{
779 version_out = this->version;
780 string str;
781 size_t pos = 0;
782 extract_variable_length_string(payload, str, pos, "usher_reply netcmd, server");
783 server = utf8(str, origin::network);
784 extract_variable_length_string(payload, pattern, pos, "usher_reply netcmd, pattern");
785 assert_end_of_buffer(payload, pos, "usher_reply netcmd payload");
786}
787
788void
789netcmd::write_usher_reply_cmd(utf8 const & server, string const & pattern)
790{
791 cmd_code = usher_reply_cmd;
792 payload.clear();
793 insert_variable_length_string(server(), payload);
794 insert_variable_length_string(pattern, payload);
795}
796
797
798
799// Local Variables:
800// mode: C++
801// fill-column: 76
802// c-file-style: "gnu"
803// indent-tabs-mode: nil
804// End:
805// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:

Archive Download this file

Branches

Tags

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