Goby Underwater Autonomy Project
Series: 1.1, revision: 163, released on 2013-02-06 14:23:27 -0500
|
00001 // copyright 2009 t. schneider tes@mit.edu 00002 // 00003 // this file is part of the Dynamic Compact Control Language (DCCL), 00004 // the goby-acomms codec. goby-acomms is a collection of libraries 00005 // for acoustic underwater networking 00006 // 00007 // This program is free software: you can redistribute it and/or modify 00008 // it under the terms of the GNU General Public License as published by 00009 // the Free Software Foundation, either version 3 of the License, or 00010 // (at your option) any later version. 00011 // 00012 // This software is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU General Public License 00018 // along with this software. If not, see <http://www.gnu.org/licenses/>. 00019 00020 #ifndef DCCL20091211H 00021 #define DCCL20091211H 00022 00023 #include <string> 00024 #include <set> 00025 #include <map> 00026 #include <ostream> 00027 #include <stdexcept> 00028 #include <vector> 00029 00030 #include "goby/util/time.h" 00031 #include "goby/util/logger.h" 00032 00033 #include "goby/core/core_constants.h" 00034 #include "message.h" 00035 #include "message_val.h" 00036 #include "dccl_exception.h" 00037 #include "goby/protobuf/dccl.pb.h" 00038 #include "goby/protobuf/modem_message.pb.h" 00039 #include "goby/acomms/acomms_helpers.h" 00040 00042 namespace goby 00043 { 00044 namespace util 00045 { class FlexOstream; } 00046 00047 00049 namespace acomms 00050 { 00052 template<typename Value> 00053 std::ostream& operator<< (std::ostream& out, const std::map<std::string, Value>& m) 00054 { 00055 typedef std::pair<std::string, Value> P; 00056 BOOST_FOREACH(const P& p, m) 00057 { 00058 out << "\t" << "key: " << p.first << std::endl 00059 << "\t" << "value: " << p.second << std::endl; 00060 } 00061 return out; 00062 } 00063 00064 template<typename Value> 00065 std::ostream& operator<< (std::ostream& out, const std::multimap<std::string, Value>& m) 00066 { 00067 typedef std::pair<std::string, Value> P; 00068 BOOST_FOREACH(const P& p, m) 00069 { 00070 out << "\t" << "key: " << p.first << std::endl 00071 << "\t" << "value: " << p.second << std::endl; 00072 } 00073 return out; 00074 } 00075 00076 00078 std::ostream& operator<< (std::ostream& out, const std::set<unsigned>& s); 00080 std::ostream& operator<< (std::ostream& out, const std::set<std::string>& s); 00081 00086 00087 class DCCLCodec 00088 { 00089 public: 00091 00092 00093 00094 DCCLCodec(std::ostream* log = 0); 00095 00097 ~DCCLCodec() {} 00099 00104 00105 00107 void set_cfg(const protobuf::DCCLConfig& cfg); 00108 00110 void merge_cfg(const protobuf::DCCLConfig& cfg); 00111 00117 void add_algorithm(const std::string& name, AlgFunction1 func); 00118 00130 void add_adv_algorithm(const std::string& name, AlgFunction2 func); 00131 00133 static void add_flex_groups(util::FlexOstream* tout); 00134 00136 00140 00141 00142 00143 00144 00145 00146 template<typename Key> 00147 void encode(const Key& k, std::string& bytes, 00148 const std::map<std::string, DCCLMessageVal>& m) 00149 { 00150 std::map<std::string, std::vector<DCCLMessageVal> > vm; 00151 00152 typedef std::pair<std::string,DCCLMessageVal> P; 00153 BOOST_FOREACH(const P& p, m) 00154 vm.insert(std::pair<std::string,std::vector<DCCLMessageVal> >(p.first, p.second)); 00155 00156 encode_private(to_iterator(k), bytes, vm); 00157 } 00158 00164 template<typename Key> 00165 void encode(const Key& k, std::string& bytes, 00166 const std::map<std::string, std::vector<DCCLMessageVal> >& m) 00167 { encode_private(to_iterator(k), bytes, m); } 00168 00169 00175 void decode(const std::string& bytes, 00176 std::map<std::string, DCCLMessageVal>& m) 00177 { 00178 std::map<std::string, std::vector<DCCLMessageVal> > vm; 00179 00180 decode_private(bytes, vm); 00181 00182 typedef std::pair<std::string,std::vector<DCCLMessageVal> > P; 00183 BOOST_FOREACH(const P& p, vm) 00184 m.insert(std::pair<std::string,DCCLMessageVal>(p.first, DCCLMessageVal(p.second))); 00185 } 00186 00192 void decode(const std::string& bytes, 00193 std::map<std::string, std::vector<DCCLMessageVal> >& m) 00194 { decode_private(bytes, m); } 00195 00196 00198 00201 00202 00203 00204 template<typename Key> 00205 std::string summary(const Key& k) const 00206 { return to_iterator(k)->get_display(); } 00208 std::string summary() const; 00209 00211 template<typename Key> 00212 std::string brief_summary(const Key& k) const 00213 { return to_iterator(k)->get_short_display(); } 00215 std::string brief_summary() const; 00216 00219 unsigned message_count() { return messages_.size(); } 00220 00222 template<typename Key> 00223 unsigned get_repeat(const Key& k) 00224 { return to_iterator(k)->repeat(); } 00225 00227 std::set<unsigned> all_message_ids(); 00229 std::set<std::string> all_message_names(); 00231 template<typename Key> 00232 std::map<std::string, std::string> message_var_names(const Key& k) const 00233 { return to_iterator(k)->message_var_names(); } 00234 00237 std::string id2name(unsigned id) {return to_iterator(id)->name();} 00240 unsigned name2id(const std::string& name) {return to_iterator(name)->id();} 00241 00242 00244 00245 00254 00256 00257 00258 00259 00260 00261 00262 00268 00269 00270 00271 00272 00273 00274 00275 00276 00277 template<typename Key> 00278 void pubsub_encode(const Key& k, 00279 protobuf::ModemDataTransmission* msg, 00280 const std::map<std::string, std::vector<DCCLMessageVal> >& pubsub_vals) 00281 { 00282 std::vector<DCCLMessage>::iterator it = to_iterator(k); 00283 00284 if(log_) 00285 { 00286 *log_ << group("dccl_enc") << "starting publish/subscribe encode for " << it->name() << std::endl; 00287 *log_ << group("dccl_enc") << "publish/subscribe variables are: " << std::endl; 00288 00289 typedef std::pair<std::string, std::vector<DCCLMessageVal> > P; 00290 BOOST_FOREACH(const P& p, pubsub_vals) 00291 { 00292 if(!p.first.empty()) 00293 { 00294 BOOST_FOREACH(const DCCLMessageVal& mv, p.second) 00295 *log_ << group("dccl_enc") << "\t" << p.first << ": " << mv << std::endl; 00296 } 00297 } 00298 } 00299 00300 00301 std::map<std::string, std::vector<DCCLMessageVal> > vals; 00302 // clean the pubsub vals into dccl vals 00303 // using <src_var/> tag, do casts from double, pull strings from key=value,key=value, etc. 00304 BOOST_FOREACH(boost::shared_ptr<DCCLMessageVar> mv, it->layout()) 00305 mv->read_pubsub_vars(vals, pubsub_vals); 00306 BOOST_FOREACH(boost::shared_ptr<DCCLMessageVar> mv, it->header()) 00307 mv->read_pubsub_vars(vals, pubsub_vals); 00308 00309 encode_private(it, msg, vals); 00310 00311 if(log_) *log_ << group("dccl_enc") << "message published to variable: " << 00312 get_outgoing_hex_var(it->id()) << std::endl; 00313 } 00314 00318 template<typename Key> 00319 void pubsub_encode(const Key& k, 00320 protobuf::ModemDataTransmission* msg, 00321 const std::map<std::string, DCCLMessageVal>& pubsub_vals) 00322 { 00323 std::map<std::string, std::vector<DCCLMessageVal> > vm; 00324 00325 typedef std::pair<std::string,DCCLMessageVal> P; 00326 BOOST_FOREACH(const P& p, pubsub_vals) 00327 vm.insert(std::pair<std::string,std::vector<DCCLMessageVal> >(p.first, p.second)); 00328 00329 pubsub_encode(k, msg, vm); 00330 } 00331 00332 00341 void pubsub_decode(const protobuf::ModemDataTransmission& msg, 00342 std::multimap<std::string, DCCLMessageVal>* pubsub_vals) 00343 00344 { 00345 std::map<std::string, std::vector<DCCLMessageVal> > vals; 00346 std::vector<DCCLMessage>::iterator it = decode_private(msg, vals); 00347 00348 // go through all the publishes_ and fill in the format strings 00349 BOOST_FOREACH(DCCLPublish& p, it->publishes()) 00350 p.write_publish(vals, pubsub_vals); 00351 00352 if(log_) 00353 { 00354 *log_ << group("dccl_dec") << "publish/subscribe variables are: " << std::endl; 00355 typedef std::pair<std::string, DCCLMessageVal> P; 00356 BOOST_FOREACH(const P& p, *pubsub_vals) 00357 { 00358 00359 *log_ << group("dccl_dec") << "\t" << p.first << ": " << p.second << std::endl; 00360 } 00361 *log_ << group("dccl_dec") << "finished publish/subscribe decode for " << it->name() << std::endl; 00362 } 00363 } 00364 00365 00367 template<typename Key> 00368 std::set<std::string> get_pubsub_src_vars(const Key& k) 00369 { return to_iterator(k)->get_pubsub_src_vars(); } 00370 00372 template<typename Key> 00373 std::set<std::string> get_pubsub_all_vars(const Key& k) 00374 { return to_iterator(k)->get_pubsub_all_vars(); } 00375 00377 template<typename Key> 00378 std::set<std::string> get_pubsub_encode_vars(const Key& k) 00379 { return to_iterator(k)->get_pubsub_encode_vars(); } 00380 00382 template<typename Key> 00383 std::set<std::string> get_pubsub_decode_vars(const Key& k) 00384 { return to_iterator(k)->get_pubsub_decode_vars(); } 00385 00387 template<typename Key> 00388 std::string get_outgoing_hex_var(const Key& k) 00389 { return to_iterator(k)->out_var(); } 00390 00392 template<typename Key> 00393 std::string get_incoming_hex_var(const Key& k) 00394 { return to_iterator(k)->in_var(); } 00395 00396 00399 bool is_publish_trigger(std::set<unsigned>& id, const std::string& key, const std::string& value); 00400 00403 bool is_time_trigger(std::set<unsigned>& id); 00404 00407 bool is_incoming(unsigned& id, const std::string& key); 00409 00410 00411 // returns a reference to all DCCLMessage objects. 00412 00413 // this is only used if one needs more control than DCCLCodec 00414 // provides 00415 std::vector<DCCLMessage>& messages() {return messages_;} 00416 00417 // grab a reference to the manipulator manager used by the loaded XML messages 00418 const ManipulatorManager& manip_manager() const { return manip_manager_; } 00419 00424 00431 00436 00441 00443 00444 private: 00449 std::set<unsigned> add_xml_message_file(const std::string& xml_file); 00450 00451 std::vector<DCCLMessage>::const_iterator to_iterator(const std::string& message_name) const; 00452 std::vector<DCCLMessage>::iterator to_iterator(const std::string& message_name); 00453 std::vector<DCCLMessage>::const_iterator to_iterator(const unsigned& id) const; 00454 std::vector<DCCLMessage>::iterator to_iterator(const unsigned& id); 00455 00456 // in map not passed by reference because we want to be able to modify it 00457 void encode_private(std::vector<DCCLMessage>::iterator it, 00458 std::string& out, 00459 std::map<std::string, std::vector<DCCLMessageVal> > in); 00460 00461 // in string not passed by reference because we want to be able to modify it 00462 std::vector<DCCLMessage>::iterator decode_private(std::string in, 00463 std::map<std::string, std::vector<DCCLMessageVal> >& out); 00464 00465 void encode_private(std::vector<DCCLMessage>::iterator it, 00466 protobuf::ModemDataTransmission* out_msg, 00467 const std::map<std::string, std::vector<DCCLMessageVal> >& in); 00468 00469 std::vector<DCCLMessage>::iterator decode_private(const protobuf::ModemDataTransmission& in_msg, 00470 std::map<std::string, std::vector<DCCLMessageVal> >& out); 00471 00472 void check_duplicates(); 00473 00474 00475 void encrypt(std::string& s, const std::string& nonce); 00476 void decrypt(std::string& s, const std::string& nonce); 00477 00478 void process_cfg(); 00479 00480 private: 00481 std::ostream* log_; 00482 00483 std::vector<DCCLMessage> messages_; 00484 std::map<std::string, size_t> name2messages_; 00485 std::map<unsigned, size_t> id2messages_; 00486 00487 protobuf::DCCLConfig cfg_; 00488 00489 boost::posix_time::ptime start_time_; 00490 00491 // SHA256 hash of the crypto passphrase 00492 std::string crypto_key_; 00493 00494 ManipulatorManager manip_manager_; 00495 00496 }; 00497 00499 std::ostream& operator<< (std::ostream& out, const DCCLCodec& d); 00500 00501 00502 class DCCLHeaderEncoder 00503 { 00504 public: 00505 DCCLHeaderEncoder(const std::map<std::string, std::vector<DCCLMessageVal> >& in) 00506 { 00507 std::map<std::string, std::vector<DCCLMessageVal> > in_copy = in; 00508 msg_.head_encode(encoded_, in_copy); 00509 } 00510 std::string& str() { return encoded_; } 00511 00512 private: 00513 DCCLMessage msg_; 00514 std::string encoded_; 00515 }; 00516 00517 class DCCLHeaderDecoder 00518 { 00519 public: 00520 DCCLHeaderDecoder(const std::string& in_orig) 00521 { 00522 std::string in = in_orig.substr(0, DCCL_NUM_HEADER_BYTES); 00523 msg_.head_decode(in, decoded_); 00524 } 00525 std::map<std::string, std::vector<DCCLMessageVal> >& get() { return decoded_; } 00526 DCCLMessageVal& operator[] (const std::string& s) 00527 { return decoded_[s][0]; } 00528 DCCLMessageVal& operator[] (DCCLHeaderPart p) 00529 { return decoded_[to_str(p)][0]; } 00530 00531 00532 private: 00533 DCCLMessage msg_; 00534 std::map<std::string, std::vector<DCCLMessageVal> > decoded_; 00535 }; 00536 } 00537 } 00538 00539 00540 #endif