26 #include "dccl/codec.h"
29 #if CRYPTOPP_PATH_USES_PLUS_SIGN
30 #include <crypto++/aes.h>
31 #include <crypto++/filters.h>
32 #include <crypto++/modes.h>
33 #include <crypto++/sha.h>
35 #include <cryptopp/aes.h>
36 #include <cryptopp/filters.h>
37 #include <cryptopp/modes.h>
38 #include <cryptopp/sha.h>
39 #endif // CRYPTOPP_PATH_USES_PLUS_SIGN
40 #endif // HAS_CRYPTOPP
42 #include "dccl/codecs2/field_codec_default.h"
43 #include "dccl/codecs3/field_codec_default.h"
44 #include "dccl/codecs3/field_codec_presence.h"
45 #include "dccl/codecs3/field_codec_var_bytes.h"
46 #include "dccl/codecs4/field_codec_default.h"
47 #include "dccl/codecs4/field_codec_default_message.h"
48 #include "dccl/field_codec_id.h"
50 #include "dccl/option_extensions.pb.h"
56 using namespace dccl::logger;
58 using google::protobuf::Descriptor;
59 using google::protobuf::FieldDescriptor;
60 using google::protobuf::Reflection;
67 : strict_(false), id_codec_(dccl_id_codec), console_width_(60)
70 FieldCodecManager::add<DefaultIdentifierCodec>(default_id_codec_name());
72 if (!library_path.empty())
80 for (std::vector<void*>::iterator it = dl_handles_.begin(), n = dl_handles_.end(); it != n;
88 void dccl::Codec::set_default_codecs()
91 static bool defaults_loaded =
false;
95 using google::protobuf::FieldDescriptor;
98 FieldCodecManager::add<v2::DefaultNumericFieldCodec<double>>(default_codec_name());
99 FieldCodecManager::add<v2::DefaultNumericFieldCodec<float>>(default_codec_name());
100 FieldCodecManager::add<v2::DefaultBoolCodec>(default_codec_name());
101 FieldCodecManager::add<v2::DefaultNumericFieldCodec<int32>>(default_codec_name());
102 FieldCodecManager::add<v2::DefaultNumericFieldCodec<int64>>(default_codec_name());
103 FieldCodecManager::add<v2::DefaultNumericFieldCodec<uint32>>(default_codec_name());
104 FieldCodecManager::add<v2::DefaultNumericFieldCodec<uint64>>(default_codec_name());
105 FieldCodecManager::add<v2::DefaultStringCodec, FieldDescriptor::TYPE_STRING>(
106 default_codec_name());
107 FieldCodecManager::add<v2::DefaultBytesCodec, FieldDescriptor::TYPE_BYTES>(
108 default_codec_name());
109 FieldCodecManager::add<v2::DefaultEnumCodec>(default_codec_name());
110 FieldCodecManager::add<v2::DefaultMessageCodec, FieldDescriptor::TYPE_MESSAGE>(
111 default_codec_name());
113 FieldCodecManager::add<v2::TimeCodec<uint64>>(
"dccl.time2");
114 FieldCodecManager::add<v2::TimeCodec<int64>>(
"dccl.time2");
115 FieldCodecManager::add<v2::TimeCodec<double>>(
"dccl.time2");
117 FieldCodecManager::add<v2::StaticCodec<std::string>>(
"dccl.static2");
118 FieldCodecManager::add<v2::StaticCodec<double>>(
"dccl.static2");
119 FieldCodecManager::add<v2::StaticCodec<float>>(
"dccl.static2");
120 FieldCodecManager::add<v2::StaticCodec<int32>>(
"dccl.static2");
121 FieldCodecManager::add<v2::StaticCodec<int64>>(
"dccl.static2");
122 FieldCodecManager::add<v2::StaticCodec<uint32>>(
"dccl.static2");
123 FieldCodecManager::add<v2::StaticCodec<uint64>>(
"dccl.static2");
126 FieldCodecManager::add<v3::DefaultNumericFieldCodec<double>>(default_codec_name(3));
127 FieldCodecManager::add<v3::DefaultNumericFieldCodec<float>>(default_codec_name(3));
128 FieldCodecManager::add<v3::DefaultBoolCodec>(default_codec_name(3));
129 FieldCodecManager::add<v3::DefaultNumericFieldCodec<int32>>(default_codec_name(3));
130 FieldCodecManager::add<v3::DefaultNumericFieldCodec<int64>>(default_codec_name(3));
131 FieldCodecManager::add<v3::DefaultNumericFieldCodec<uint32>>(default_codec_name(3));
132 FieldCodecManager::add<v3::DefaultNumericFieldCodec<uint64>>(default_codec_name(3));
133 FieldCodecManager::add<v3::DefaultStringCodec, FieldDescriptor::TYPE_STRING>(
134 default_codec_name(3));
135 FieldCodecManager::add<v3::DefaultBytesCodec, FieldDescriptor::TYPE_BYTES>(
136 default_codec_name(3));
137 FieldCodecManager::add<v3::DefaultEnumCodec>(default_codec_name(3));
138 FieldCodecManager::add<v3::DefaultMessageCodec, FieldDescriptor::TYPE_MESSAGE>(
139 default_codec_name(3));
142 FieldCodecManager::add<v4::DefaultNumericFieldCodec<double>>(default_codec_name(4));
143 FieldCodecManager::add<v4::DefaultNumericFieldCodec<float>>(default_codec_name(4));
144 FieldCodecManager::add<v4::DefaultBoolCodec>(default_codec_name(4));
145 FieldCodecManager::add<v4::DefaultNumericFieldCodec<int32>>(default_codec_name(4));
146 FieldCodecManager::add<v4::DefaultNumericFieldCodec<int64>>(default_codec_name(4));
147 FieldCodecManager::add<v4::DefaultNumericFieldCodec<uint32>>(default_codec_name(4));
148 FieldCodecManager::add<v4::DefaultNumericFieldCodec<uint64>>(default_codec_name(4));
149 FieldCodecManager::add<v4::DefaultStringCodec, FieldDescriptor::TYPE_STRING>(
150 default_codec_name(4));
151 FieldCodecManager::add<v4::DefaultBytesCodec, FieldDescriptor::TYPE_BYTES>(
152 default_codec_name(4));
153 FieldCodecManager::add<v4::DefaultEnumCodec>(default_codec_name(4));
154 FieldCodecManager::add<v4::DefaultMessageCodec, FieldDescriptor::TYPE_MESSAGE>(
155 default_codec_name(4));
158 FieldCodecManager::add<v3::PresenceBitCodec<v3::DefaultNumericFieldCodec<double>>>(
160 FieldCodecManager::add<v3::PresenceBitCodec<v3::DefaultNumericFieldCodec<float>>>(
162 FieldCodecManager::add<v3::PresenceBitCodec<v3::DefaultNumericFieldCodec<int32>>>(
164 FieldCodecManager::add<v3::PresenceBitCodec<v3::DefaultNumericFieldCodec<int64>>>(
166 FieldCodecManager::add<v3::PresenceBitCodec<v3::DefaultNumericFieldCodec<uint32>>>(
168 FieldCodecManager::add<v3::PresenceBitCodec<v3::DefaultNumericFieldCodec<uint64>>>(
170 FieldCodecManager::add<v3::PresenceBitCodec<v3::DefaultEnumCodec>>(
"dccl.presence");
173 FieldCodecManager::add<v3::VarBytesCodec, FieldDescriptor::TYPE_BYTES>(
"dccl.var_bytes");
176 FieldCodecManager::add<v2::TimeCodec<uint64>>(
"_time");
177 FieldCodecManager::add<v2::TimeCodec<int64>>(
"_time");
178 FieldCodecManager::add<v2::TimeCodec<double>>(
"_time");
180 FieldCodecManager::add<v2::StaticCodec<std::string>>(
"_static");
181 FieldCodecManager::add<v2::StaticCodec<double>>(
"_static");
182 FieldCodecManager::add<v2::StaticCodec<float>>(
"_static");
183 FieldCodecManager::add<v2::StaticCodec<int32>>(
"_static");
184 FieldCodecManager::add<v2::StaticCodec<int64>>(
"_static");
185 FieldCodecManager::add<v2::StaticCodec<uint32>>(
"_static");
186 FieldCodecManager::add<v2::StaticCodec<uint64>>(
"_static");
188 defaults_loaded =
true;
195 const Descriptor* desc = msg.GetDescriptor();
197 dlog.
is(DEBUG1, ENCODE) && dlog <<
"Began encoding message of type: " << desc->full_name()
202 unsigned dccl_id = (user_id < 0) ?
id(desc) : user_id;
203 size_t head_byte_size = 0;
205 if (!msg.IsInitialized() && !header_only)
207 std::stringstream ss;
209 ss <<
"Message is not properly initialized. All `required` fields must be set. Fields "
211 << get_all_error_fields_in_message(msg);
216 if (!id2desc_.count(dccl_id))
217 throw(
Exception(
"Message id " + boost::lexical_cast<std::string>(dccl_id) +
218 " has not been loaded. Call load() before encoding this type."));
221 boost::shared_ptr<internal::FromProtoCppTypeBase> helper = internal::TypeHelper::find(desc);
226 id_codec()->field_encode(&head_bits, dccl_id, 0);
229 msg_stack.push(msg.GetDescriptor());
230 codec->base_encode(&head_bits, msg, HEAD, strict_);
233 head_byte_size = ceil_bits2bytes(head_bits.size());
234 head_bits.resize(head_byte_size * BITS_IN_BYTE);
238 dlog.
is(DEBUG2, ENCODE) &&
239 dlog <<
"as requested, skipping encoding and encrypting body." << std::endl;
243 codec->base_encode(&body_bits, msg, BODY, strict_);
248 throw(
Exception(
"Failed to find (dccl.msg).codec `" +
249 desc->options().GetExtension(dccl::msg).codec() +
"`"));
254 dlog.
is(DEBUG1, ENCODE) &&
255 dlog <<
"Message " << desc->full_name()
256 <<
" failed to encode because a field was out of bounds and strict == true: "
257 << e.what() << std::endl;
260 catch (std::exception& e)
262 std::stringstream ss;
264 ss <<
"Message " << desc->full_name() <<
" failed to encode. Reason: " << e.what();
266 dlog.
is(DEBUG1, ENCODE) && dlog << ss.str() << std::endl;
272 bool header_only ,
int user_id )
274 const Descriptor* desc = msg.GetDescriptor();
277 encode_internal(msg, header_only, head_bits, body_bits, user_id);
279 size_t head_byte_size = ceil_bits2bytes(head_bits.size());
280 if (max_len < head_byte_size)
282 throw std::length_error(
"max_len must be >= head_byte_size");
286 dlog.
is(DEBUG2, ENCODE) && dlog <<
"Head bytes (bits): " << head_byte_size <<
"("
287 << head_bits.size() <<
")" << std::endl;
288 dlog.
is(DEBUG3, ENCODE) && dlog <<
"Unencrypted Head (bin): " << head_bits << std::endl;
289 dlog.
is(DEBUG3, ENCODE) && dlog <<
"Unencrypted Head (hex): "
290 <<
hex_encode(bytes, bytes + head_byte_size) << std::endl;
292 size_t body_byte_size = 0;
295 body_byte_size = ceil_bits2bytes(body_bits.size());
296 if (max_len < (head_byte_size + body_byte_size))
298 throw std::length_error(
"max_len must be >= (head_byte_size + body_byte_size)");
300 body_bits.
to_byte_string(bytes + head_byte_size, max_len - head_byte_size);
302 dlog.
is(DEBUG3, ENCODE) && dlog <<
"Unencrypted Body (bin): " << body_bits << std::endl;
303 dlog.
is(DEBUG3, ENCODE) &&
304 dlog <<
"Unencrypted Body (hex): "
305 <<
hex_encode(bytes + head_byte_size, bytes + head_byte_size + body_byte_size)
307 dlog.
is(DEBUG2, ENCODE) && dlog <<
"Body bytes (bits): " << body_byte_size <<
"("
308 << body_bits.size() <<
")" << std::endl;
310 unsigned dccl_id = (user_id < 0) ?
id(desc) : user_id;
311 if (!crypto_key_.empty() && !skip_crypto_ids_.count(dccl_id))
313 std::string head_bytes(bytes, bytes + head_byte_size);
314 std::string body_bytes(bytes + head_byte_size, bytes + head_byte_size + body_byte_size);
315 encrypt(&body_bytes, head_bytes);
316 std::memcpy(bytes + head_byte_size, body_bytes.data(), body_bytes.size());
319 dlog.
is(logger::DEBUG3, logger::ENCODE) &&
320 dlog <<
"Encrypted Body (hex): "
321 <<
hex_encode(bytes + head_byte_size, bytes + head_byte_size + body_byte_size)
325 dlog.
is(DEBUG1, ENCODE) && dlog <<
"Successfully encoded message of type: " << desc->full_name()
328 return head_byte_size + body_byte_size;
332 bool header_only ,
int user_id )
334 const Descriptor* desc = msg.GetDescriptor();
337 encode_internal(msg, header_only, head_bits, body_bits, user_id);
341 dlog.
is(DEBUG2, ENCODE) && dlog <<
"Head bytes (bits): " << head_bytes.size() <<
"("
342 << head_bits.size() <<
")" << std::endl;
343 dlog.
is(DEBUG3, ENCODE) && dlog <<
"Unencrypted Head (bin): " << head_bits << std::endl;
344 dlog.
is(DEBUG3, ENCODE) && dlog <<
"Unencrypted Head (hex): " <<
hex_encode(head_bytes)
347 std::string body_bytes;
352 dlog.
is(DEBUG3, ENCODE) && dlog <<
"Unencrypted Body (bin): " << body_bits << std::endl;
353 dlog.
is(DEBUG3, ENCODE) && dlog <<
"Unencrypted Body (hex): " <<
hex_encode(body_bytes)
355 dlog.
is(DEBUG2, ENCODE) && dlog <<
"Body bytes (bits): " << body_bytes.size() <<
"("
356 << body_bits.size() <<
")" << std::endl;
358 unsigned dccl_id = (user_id < 0) ?
id(desc) : user_id;
359 if (!crypto_key_.empty() && !skip_crypto_ids_.count(dccl_id))
360 encrypt(&body_bytes, head_bytes);
362 dlog.
is(logger::DEBUG3, logger::ENCODE) &&
363 dlog <<
"Encrypted Body (hex): " <<
hex_encode(body_bytes) << std::endl;
366 dlog.
is(DEBUG1, ENCODE) && dlog <<
"Successfully encoded message of type: " << desc->full_name()
368 *bytes += head_bytes + body_bytes;
371 unsigned dccl::Codec::id(
const std::string& bytes)
const {
return id(bytes.begin(), bytes.end()); }
376 unsigned last_size = size(*msg);
377 bytes->erase(0, last_size);
383 decode(bytes.begin(), bytes.end(), msg, header_only);
392 if (user_id < 0 && !desc->options().GetExtension(dccl::msg).has_id())
394 Exception(
"Missing message option `(dccl.msg).id`. Specify a unique id (e.g. 3) in "
395 "the body of your .proto message using \"option (dccl.msg).id = 3\""));
396 if (!desc->options().GetExtension(dccl::msg).has_max_bytes())
397 throw(
Exception(
"Missing message option `(dccl.msg).max_bytes`. Specify a maximum "
398 "(encoded) message size in bytes (e.g. 32) in the body of your .proto "
399 "message using \"option (dccl.msg).max_bytes = 32\""));
401 if (!desc->options().GetExtension(dccl::msg).has_codec_version())
402 throw(
Exception(
"No (dccl.msg).codec_version set for DCCL Message '" +
404 "'. For new messages, set 'option (dccl.msg).codec_version = 4' in the "
405 "message definition for " +
406 desc->full_name() +
" to use the default DCCL4 codecs."));
410 unsigned dccl_id = (user_id < 0) ?
id(desc) : user_id;
411 unsigned head_size_bits, body_size_bits;
412 codec->base_max_size(&head_size_bits, desc, HEAD);
413 codec->base_max_size(&body_size_bits, desc, BODY);
415 unsigned id_bits = 0;
416 id_codec()->field_size(&id_bits, dccl_id, 0);
417 head_size_bits += id_bits;
419 const unsigned byte_size =
420 ceil_bits2bytes(head_size_bits) + ceil_bits2bytes(body_size_bits);
422 if (byte_size > desc->options().GetExtension(dccl::msg).max_bytes())
424 "Actual maximum size of message exceeds allowed maximum (dccl.max_bytes). Tighten "
425 "bounds, remove fields, improve codecs, or increase the allowed dccl.max_bytes"));
427 codec->base_validate(desc, HEAD);
428 codec->base_validate(desc, BODY);
430 if (id2desc_.count(dccl_id) && desc != id2desc_.find(dccl_id)->second)
431 throw(
Exception(
"`dccl id` " + boost::lexical_cast<std::string>(dccl_id) +
432 " is already in use by Message " +
433 id2desc_.find(dccl_id)->second->full_name() +
": " +
434 boost::lexical_cast<std::string>(id2desc_.find(dccl_id)->second)));
436 id2desc_.insert(std::make_pair(dccl_id, desc));
438 dlog.
is(DEBUG1) && dlog <<
"Successfully validated message of type: " << desc->full_name()
451 dlog.
is(DEBUG1) && dlog <<
"Message " << desc->full_name() <<
": " << desc
452 <<
" failed validation. Reason: " << e.what() <<
"\n"
453 <<
"If possible, information about the Message are printed above. "
462 unsigned int erased = 0;
463 for (std::map<int32, const google::protobuf::Descriptor*>::iterator it = id2desc_.begin();
464 it != id2desc_.end();)
466 if (it->second == desc)
469 id2desc_.erase(it++);
478 dlog.
is(DEBUG1) && dlog <<
"Message " << desc->full_name()
479 <<
": is not loaded. Ignoring unload request." << std::endl;
485 if (id2desc_.count(dccl_id))
487 id2desc_.erase(dccl_id);
491 dlog.
is(DEBUG1) && dlog <<
"Message with id " << dccl_id
492 <<
": is not loaded. Ignoring unload request." << std::endl;
499 const Descriptor* desc = msg.GetDescriptor();
503 unsigned dccl_id = (user_id < 0) ?
id(desc) : user_id;
504 unsigned head_size_bits;
505 codec->base_size(&head_size_bits, msg, HEAD);
507 unsigned id_bits = 0;
508 id_codec()->field_size(&id_bits, dccl_id, 0);
509 head_size_bits += id_bits;
511 unsigned body_size_bits;
512 codec->base_size(&body_size_bits, msg, BODY);
514 const unsigned head_size_bytes = ceil_bits2bytes(head_size_bits);
515 const unsigned body_size_bytes = ceil_bits2bytes(body_size_bits);
516 return head_size_bytes + body_size_bytes;
523 unsigned head_size_bits;
524 codec->base_max_size(&head_size_bits, desc, HEAD);
526 unsigned id_bits = 0;
527 id_codec()->field_max_size(&id_bits, 0);
528 head_size_bits += id_bits;
530 unsigned body_size_bits;
531 codec->base_max_size(&body_size_bits, desc, BODY);
533 const unsigned head_size_bytes = ceil_bits2bytes(head_size_bits);
534 const unsigned body_size_bytes = ceil_bits2bytes(body_size_bits);
535 return head_size_bytes + body_size_bytes;
542 unsigned head_size_bits;
543 codec->base_min_size(&head_size_bits, desc, HEAD);
545 unsigned id_bits = 0;
546 id_codec()->field_min_size(&id_bits, 0);
547 head_size_bits += id_bits;
549 unsigned body_size_bits;
550 codec->base_min_size(&body_size_bits, desc, BODY);
552 const unsigned head_size_bytes = ceil_bits2bytes(head_size_bits);
553 const unsigned body_size_bytes = ceil_bits2bytes(body_size_bits);
554 return head_size_bytes + body_size_bytes;
560 std::ostream* os = (param_os) ? param_os : &dlog;
562 if (param_os || dlog.
is(INFO))
568 unsigned config_head_bit_size, body_bit_size;
569 codec->base_max_size(&config_head_bit_size, desc, HEAD);
570 codec->base_max_size(&body_bit_size, desc, BODY);
572 unsigned dccl_id = (user_id < 0) ?
id(desc) : user_id;
573 unsigned id_bit_size = 0;
574 id_codec()->field_size(&id_bit_size, dccl_id, 0);
576 const unsigned bit_size = id_bit_size + config_head_bit_size + body_bit_size;
578 const unsigned byte_size = ceil_bits2bytes(config_head_bit_size + id_bit_size) +
579 ceil_bits2bytes(body_bit_size);
581 const unsigned allowed_byte_size = desc->options().GetExtension(dccl::msg).max_bytes();
582 const unsigned allowed_bit_size = allowed_byte_size * BITS_IN_BYTE;
584 std::string message_name =
585 boost::lexical_cast<std::string>(dccl_id) +
": " + desc->full_name();
586 std::string guard = build_guard_for_console_output(message_name,
'=');
587 std::string bits_dccl_head_str =
"dccl.id head";
588 std::string bits_user_head_str =
"user head";
589 std::string bits_body_str =
"body";
590 std::string bits_padding_str =
"padding to full byte";
592 const int bits_width = 40;
593 const int spaces = 8;
594 std::string indent = std::string(spaces,
' ');
596 *os << guard <<
" " << message_name <<
" " << guard <<
"\n"
597 <<
"Actual maximum size of message: " << byte_size <<
" bytes / "
598 << byte_size * BITS_IN_BYTE <<
" bits\n"
599 << indent << bits_dccl_head_str << std::setfill(
'.')
600 << std::setw(bits_width - bits_dccl_head_str.size()) << id_bit_size <<
"\n"
601 << indent << bits_user_head_str << std::setfill(
'.')
602 << std::setw(bits_width - bits_user_head_str.size()) << config_head_bit_size <<
"\n"
603 << indent << bits_body_str << std::setfill(
'.')
604 << std::setw(bits_width - bits_body_str.size()) << body_bit_size <<
"\n"
605 << indent << bits_padding_str << std::setfill(
'.')
606 << std::setw(bits_width - bits_padding_str.size())
607 << byte_size * BITS_IN_BYTE - bit_size <<
"\n"
608 <<
"Allowed maximum size of message: " << allowed_byte_size <<
" bytes / "
609 << allowed_bit_size <<
" bits\n";
611 std::string header_str =
"Header";
612 std::string header_guard = build_guard_for_console_output(header_str,
'-');
614 *os << header_guard <<
" " << header_str <<
" " << header_guard << std::endl;
615 *os << bits_dccl_head_str << std::setfill(
'.')
616 << std::setw(bits_width - bits_dccl_head_str.size() + spaces) << id_bit_size <<
" {"
617 << id_codec()->name() <<
"}\n";
618 codec->base_info(os, desc, HEAD);
621 std::string body_str =
"Body";
622 std::string body_guard = build_guard_for_console_output(body_str,
'-');
624 *os << body_guard <<
" " << body_str <<
" " << body_guard << std::endl;
625 codec->base_info(os, desc, BODY);
633 dlog <<
"Message " << desc->full_name()
634 <<
" cannot provide information due to invalid configuration. Reason: "
635 << e.what() << std::endl;
642 void dccl::Codec::encrypt(std::string* s,
const std::string& nonce )
644 #if DCCL_HAS_CRYPTOPP
645 using namespace CryptoPP;
649 StringSource unused(nonce,
true,
new HashFilter(hash,
new StringSink(iv)));
651 CTR_Mode<AES>::Encryption encryptor;
652 encryptor.SetKeyWithIV((
byte*)crypto_key_.c_str(), crypto_key_.size(), (
byte*)iv.c_str());
655 StreamTransformationFilter in(encryptor,
new StringSink(cipher));
656 in.Put((
byte*)s->c_str(), s->size());
662 void dccl::Codec::decrypt(std::string* s,
const std::string& nonce)
664 #if DCCL_HAS_CRYPTOPP
665 using namespace CryptoPP;
669 StringSource unused(nonce,
true,
new HashFilter(hash,
new StringSink(iv)));
671 CTR_Mode<AES>::Decryption decryptor;
672 decryptor.SetKeyWithIV((
byte*)crypto_key_.c_str(), crypto_key_.size(), (
byte*)iv.c_str());
674 std::string recovered;
676 StreamTransformationFilter out(decryptor,
new StringSink(recovered));
677 out.Put((
byte*)s->c_str(), s->size());
685 void* handle = dlopen(library_path.c_str(), RTLD_LAZY);
687 dl_handles_.push_back(handle);
688 load_library(handle);
694 throw(
Exception(
"Null shared library handle passed to load_library"));
698 dccl_load_ptr = (void (*)(
dccl::Codec*))dlsym(dl_handle,
"dccl3_load");
700 (*dccl_load_ptr)(
this);
706 throw(
Exception(
"Null shared library handle passed to unload_library"));
710 dccl_unload_ptr = (void (*)(
dccl::Codec*))dlsym(dl_handle,
"dccl3_unload");
712 (*dccl_unload_ptr)(
this);
716 const std::string& passphrase,
717 const std::set<unsigned>& do_not_encrypt_ids_ )
719 if (!crypto_key_.empty())
721 skip_crypto_ids_.clear();
723 #if DCCL_HAS_CRYPTOPP
724 using namespace CryptoPP;
727 StringSource unused(passphrase,
true,
new HashFilter(hash,
new StringSink(crypto_key_)));
729 dlog.
is(DEBUG1) && dlog <<
"Cryptography enabled with given passphrase" << std::endl;
731 dlog.
is(DEBUG1) && dlog <<
"Cryptography disabled because DCCL was compiled without support of "
732 "Crypto++. Install Crypto++ and recompile to enable cryptography."
736 skip_crypto_ids_ = do_not_encrypt_ids_;
741 std::ostream* os = (param_os) ? param_os : &dlog;
743 if (param_os || dlog.
is(INFO))
745 std::string codec_str =
"Dynamic Compact Control Language (DCCL) Codec";
746 std::string codec_guard = build_guard_for_console_output(codec_str,
'|');
748 *os << codec_guard <<
" " << codec_str <<
" " << codec_guard << std::endl;
749 *os << id2desc_.size() <<
" messages loaded.\n";
750 *os <<
"Field sizes are in bits unless otherwise noted." << std::endl;
752 for (std::map<int32, const google::protobuf::Descriptor*>::const_iterator
753 it = id2desc_.begin(),
756 info(it->second, os, it->first);
767 id_codec_ = id_codec_name;
772 std::string dccl::Codec::build_guard_for_console_output(std::string& base,
char guard_char)
const
775 return (base.size() < console_width_)
776 ? std::string((console_width_ - base.size()) / 2, guard_char)
788 std::stringstream output_stream;
790 const google::protobuf::Descriptor* descriptor = message.GetDescriptor();
791 const google::protobuf::Reflection* reflection = message.GetReflection();
792 const uint8_t depth_spacing = 4;
795 const int32_t field_count = descriptor->field_count();
797 for (int32_t index = 0; index < field_count; ++index)
799 if (descriptor->field(index)->is_required())
801 if (!reflection->HasField(message, descriptor->field(index)))
803 output_stream << std::string(depth * depth_spacing,
' ')
804 << descriptor->field(index)->number() <<
": "
805 << descriptor->field(index)->name() <<
"\n";
811 std::vector<const google::protobuf::FieldDescriptor*> fields;
812 reflection->ListFields(message, &fields);
814 for (
const google::protobuf::FieldDescriptor* field : fields)
816 if (field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)
818 output_stream << std::string(depth * depth_spacing,
' ') << field->number() <<
": "
819 << field->name() <<
"\n";
821 if (field->is_repeated())
823 int32_t size = reflection->FieldSize(message, field);
825 for (int32_t index = 0; index < size; ++index)
828 reflection->GetRepeatedMessage(message, field, index);
830 output_stream << std::string((depth + 1) * depth_spacing,
' ') <<
"[" << index
834 output_stream << get_all_error_fields_in_message(sub_message, depth + 2);
840 reflection->GetMessage(message, field);
841 output_stream << get_all_error_fields_in_message(sub_message, depth + 1);
846 return output_stream.str();