Note: Goby version 1 (shown here) is now considered obsolete. Please use version 2 for new projects, and consider upgrading old projects.

Goby Underwater Autonomy Project  Series: 1.1, revision: 163, released on 2013-02-06 14:23:27 -0500
acomms/libdccl/dccl.h
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends