xorp

message.hh

00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
00002 // vim:set sts=4 ts=8 sw=4:
00003 
00004 // Copyright (c) 2001-2012 XORP, Inc and Others
00005 //
00006 // This program is free software; you can redistribute it and/or modify
00007 // it under the terms of the GNU General Public License, Version 2, June
00008 // 1991 as published by the Free Software Foundation. Redistribution
00009 // and/or modification of this program under the terms of any other
00010 // version of the GNU General Public License is not permitted.
00011 // 
00012 // This program is distributed in the hope that it will be useful, but
00013 // WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
00015 // see the GNU General Public License, Version 2, a copy of which can be
00016 // found in the XORP LICENSE.gpl file.
00017 // 
00018 // XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
00019 // http://xorp.net
00020 
00021 // $XORP: xorp/contrib/olsr/message.hh,v 1.4 2008/10/02 21:56:34 bms Exp $
00022 
00023 #ifndef __OLSR_MESSAGE_HH__
00024 #define __OLSR_MESSAGE_HH__
00025 
00029 class Message {
00030 public:
00031     virtual ~Message() {}
00032 
00033     inline TimeVal  receive_time() const
00034     { return _receive_time; }
00035 
00036     inline TimeVal  expiry_time() const
00037     { return _expiry_time; }
00038 
00039     inline bool     valid() const
00040     { return _is_valid; }
00041 
00042     inline bool     is_first() const
00043     { return _is_first; }
00044 
00045     inline bool     is_last() const
00046     { return _is_last; }
00047 
00048     inline void     set_is_first(bool arg)
00049     { _is_first = arg; }
00050 
00051     inline void     set_is_last(bool arg)
00052     { _is_last = arg; }
00053 
00054     inline bool     forwarded() const
00055     { return _is_forwarded; }
00056 
00057     inline OlsrTypes::FaceID    faceid() const
00058     { return _faceid; }
00059 
00060     inline uint8_t  hops() const
00061     { return _hops; }
00062 
00063     inline void     incr_hops() { ++_hops; }
00064 
00065     inline uint16_t seqno() const
00066     { return _seqno; }
00067 
00068     inline uint8_t  ttl() const
00069     { return _ttl; }
00070 
00071     inline void     decr_ttl() { --_ttl; }
00072 
00073     inline IPv4     origin() const
00074     { return _origin; }
00075 
00076     inline OlsrTypes::MessageType   type() const
00077     { return _type; }
00078 
00079     inline void set_hop_count(uint8_t hops)
00080     { _hops = hops; }
00081 
00082     inline void set_forwarded(bool is_forwarded)
00083     { _is_forwarded = is_forwarded; }
00084 
00085     inline void set_expiry_time(const TimeVal& expiry_time)
00086     { _expiry_time = expiry_time; }
00087 
00088     inline void set_receive_time(const TimeVal& receive_time)
00089     { _receive_time = receive_time; }
00090 
00091     inline void set_seqno(uint16_t seqno)
00092     { _seqno = seqno; }
00093 
00094     inline void set_ttl(uint8_t ttl)
00095     { _ttl = ttl; }
00096 
00097     inline void set_type(OlsrTypes::MessageType type)
00098     { _type = type; }
00099 
00100     inline void set_valid(bool is_valid)
00101     { _is_valid = is_valid; }
00102 
00103     inline void set_origin(IPv4 origin)
00104     { _origin = origin; }
00105 
00106     inline void set_faceid(OlsrTypes::FaceID faceid)
00107     { _faceid = faceid; }
00108 
00109     virtual Message* decode(uint8_t* buf, size_t& len)
00110     throw(InvalidMessage) = 0;
00111 
00112     virtual bool encode(uint8_t* buf, size_t& len) = 0;
00113 
00114     virtual size_t  length() const = 0;
00115 
00116     virtual string str() const = 0;
00117 
00118     string common_str() const;
00119 
00120     /*
00121      * @return the length of the header common to all types of OLSR
00122      *         protocol message.
00123      * As this varies according to the protocol family in use, it needs
00124      * to become templatized.
00125      */
00126     static size_t get_common_header_length() {
00127     return  sizeof(uint8_t) +   // message type
00128         sizeof(uint8_t) +   // validity time
00129         sizeof(uint16_t) +  // message size (if not RA-OLSR)
00130         IPv4::addr_bytelen() +  // IPv4 origin: family dependent
00131         sizeof(uint8_t) +   // time-to-live
00132         sizeof(uint8_t) +   // hop count
00133         sizeof(uint16_t);   // message sequence number
00134     }
00135 
00136     uint16_t adv_message_length() const { return _adv_message_length; }
00137 
00138 protected:
00139     size_t decode_common_header(uint8_t* buf, size_t& len)
00140     throw(InvalidMessage);
00141 
00142     bool encode_common_header(uint8_t* buf, size_t& len);
00143 
00144     void store(uint8_t* ptr, size_t len) {
00145     _msg.resize(len);
00146     memcpy(&_msg[0], ptr, len);
00147     }
00148 
00149 protected:
00150     // common message data and fields
00151     TimeVal _receive_time;  // time when this message was received
00152     TimeVal _expiry_time;   // this message will self destruct in
00153                 // C*(1+a/16)* 2^b seconds!
00154     bool    _is_valid;  // this message is valid
00155     bool    _is_forwarded;  // this message has already been forwarded
00156     bool    _is_first;  // this message is the first in the packet
00157     bool    _is_last;   // this message is the last in the packet
00158     OlsrTypes::FaceID   _faceid;    // interface where this was received
00159     IPv4    _origin;    // who sent it
00160     uint8_t _type;      // type of message
00161     uint8_t _ttl;       // time-to-live; updated when forwarded
00162     uint8_t _hops;      // hop count; updated when forwarded
00163     uint16_t    _seqno;     // message sequence number
00164 
00165     uint16_t    _adv_message_length;    // length field seen on wire; used by
00166                         // derived class decoders.
00167 
00168     vector<uint8_t> _msg;   // on-wire format
00169 };
00170 
00174 class LinkCode {
00175 private:
00176     static const char* linktype_to_str(OlsrTypes::LinkType t);
00177     static const char* neighbortype_to_str(OlsrTypes::NeighborType t);
00178 public:
00179     LinkCode() : _linkcode(OlsrTypes::UNSPEC_LINK) { }
00180 
00181     LinkCode(OlsrTypes::NeighborType ntype, OlsrTypes::LinkType ltype)
00182      throw(BadLinkCode) {
00183     _linkcode = ((ntype << 2) & 0x0C) | (ltype & 0x03);
00184     throw_if_not_valid();
00185     }
00186 
00187     LinkCode(uint8_t code)
00188      throw(BadLinkCode)
00189      :  _linkcode(code) {
00190     throw_if_not_valid();
00191     }
00192 
00193     LinkCode(const LinkCode& rhs)
00194      : _linkcode(rhs._linkcode)
00195     {}
00196 
00197     inline LinkCode& operator=(const uint8_t& rhs)
00198      throw(BadLinkCode) {
00199     _linkcode = rhs;
00200     throw_if_not_valid();
00201     return (*this);
00202     }
00203 
00204     inline operator uint8_t() const {
00205     return _linkcode;
00206     }
00207 
00208     inline OlsrTypes::NeighborType neighbortype() const {
00209     return (_linkcode & 0x0C) >> 2;
00210     }
00211 
00212     inline OlsrTypes::LinkType linktype() const {
00213     return _linkcode & 0x03;
00214     }
00215 
00216     inline bool is_unspec_link() const {
00217     return linktype() == OlsrTypes::UNSPEC_LINK;
00218     }
00219 
00220     inline bool is_asym_link() const {
00221     return linktype() == OlsrTypes::ASYM_LINK;
00222     }
00223 
00224     inline bool is_sym_link() const {
00225     return linktype() == OlsrTypes::SYM_LINK;
00226     }
00227 
00228     inline bool is_lost_link() const {
00229     return linktype() == OlsrTypes::LOST_LINK;
00230     }
00231 
00232     inline bool is_mpr_neighbor() const {
00233     return neighbortype() == OlsrTypes::MPR_NEIGH;
00234     }
00235 
00236     inline bool is_sym_neighbor() const {
00237     return neighbortype() == OlsrTypes::SYM_NEIGH;
00238     }
00239 
00240     inline bool is_not_neighbor() const {
00241     return neighbortype() == OlsrTypes::NOT_NEIGH;
00242     }
00243 
00244     inline string str() const {
00245     return c_format("link %s neighbor %s",
00246         linktype_to_str(linktype()), neighbortype_to_str(neighbortype()));
00247     }
00248 
00249 private:
00250     inline void throw_if_not_valid() {
00251     if (!is_valid()) {
00252         xorp_throw(BadLinkCode,
00253                c_format("Bad link code: neighbor %u link %u",
00254                     XORP_UINT_CAST(neighbortype()),
00255                     XORP_UINT_CAST(linktype())));
00256     }
00257     }
00258 
00259     inline bool is_valid() {
00260     if (linktype() > OlsrTypes::LINKTYPE_END ||
00261         neighbortype() > OlsrTypes::NEIGHBORTYPE_END ||
00262         (linktype() == OlsrTypes::SYM_LINK &&
00263          neighbortype() == OlsrTypes::NOT_NEIGH)) {
00264         return false;
00265     }
00266     return true;
00267     }
00268 
00269 private:
00270     uint8_t _linkcode;
00271 };
00272 
00273 
00279 class LinkAddrInfo {
00280 public:
00281     explicit LinkAddrInfo(const bool has_lq)
00282      : _has_etx(has_lq)
00283     {}
00284 
00285     explicit LinkAddrInfo(const IPv4& addr)
00286      : _has_etx(false), _remote_addr(addr)
00287     {}
00288 
00289     explicit LinkAddrInfo(const IPv4& addr,
00290     const double& near_etx, const double& far_etx)
00291      : _has_etx(true),
00292        _remote_addr(addr),
00293        _near_etx(near_etx),
00294        _far_etx(far_etx)
00295     {}
00296 #ifdef XORP_USE_USTL
00297     LinkAddrInfo() { }
00298 #endif
00299 
00300     bool has_etx() const { return _has_etx; }
00301     IPv4 remote_addr() const { return _remote_addr; }
00302     double near_etx() const { return _near_etx; }
00303     double far_etx() const { return _far_etx; }
00304 
00305     inline size_t size() const {
00306     size_t byte_count = IPv4::addr_bytelen();
00307     if (has_etx())
00308         byte_count += (sizeof(uint8_t) * 2);
00309     return byte_count;
00310     }
00311 
00312     size_t copy_in(const uint8_t *from_uint8);
00313     size_t copy_out(uint8_t* to_uint8) const;
00314 
00315     inline string str() const {
00316     string str = _remote_addr.str();
00317     if (has_etx()) {
00318         str += c_format("[nq %.2f, fq %.2f]",
00319                 near_etx(),
00320                 far_etx());
00321     }
00322     return str;
00323     }
00324 
00325 private:
00326     bool    _has_etx;
00327     IPv4    _remote_addr;
00328 
00329     double  _near_etx;
00330     double  _far_etx;
00331 };
00332 
00336 class HelloMessage : public Message {
00337 public:
00338     typedef multimap<LinkCode, LinkAddrInfo> LinkBag;
00339 
00340 public:
00341     HelloMessage()
00342     { this->set_type(OlsrTypes::HELLO_MESSAGE); }
00343     ~HelloMessage() {}
00344 
00345     Message* decode(uint8_t* buf, size_t& len) throw(InvalidMessage);
00346     bool encode(uint8_t* buf, size_t& len);
00347 
00348     inline size_t   min_length() const {
00349     return      get_common_header_length() +
00350             sizeof(uint16_t) + // reserved
00351             sizeof(uint8_t) +   // Htime
00352             sizeof(uint8_t);    // Willingness
00353     }
00354 
00355     size_t  length() const {
00356     size_t len = get_common_header_length() +
00357              sizeof(uint16_t) + // reserved
00358              sizeof(uint8_t) +  // Htime
00359              sizeof(uint8_t) +  // Willingness
00360              get_links_length();
00361     return (len);
00362     }
00363 
00364     inline const TimeVal get_htime() const
00365     { return _htime; }
00366 
00367     inline void set_htime(const TimeVal& htime)
00368     { _htime = htime; }
00369 
00370     inline OlsrTypes::WillType willingness() const
00371     { return _willingness; }
00372 
00373     inline void set_willingness(OlsrTypes::WillType willingness)
00374     { _willingness = willingness; }
00375 
00376     inline void add_link(const LinkCode code, const IPv4& remote_addr) {
00377     add_link(code, LinkAddrInfo(remote_addr));
00378     }
00379 
00383     size_t remove_link(const IPv4& remote_addr);
00384 
00385     inline void clear() {
00386     _htime = TimeVal::ZERO();
00387     _willingness = OlsrTypes::WILL_DEFAULT;
00388     _links.clear();
00389     }
00390 
00391     inline const LinkBag& links() const { return _links; }
00392 
00396     virtual string str() const;
00397 
00401     virtual size_t get_links_length() const;
00402 
00403 protected:
00404     inline void add_link(const LinkCode code,
00405              const LinkAddrInfo& lai) {
00406     _links.insert(make_pair(code, lai));
00407     }
00408 
00423     virtual size_t decode_link_tuple(uint8_t* buf, size_t& len,
00424         size_t& skiplen, bool has_lq = false)
00425     throw(InvalidLinkTuple);
00426 
00427     inline size_t link_tuple_header_length() const {
00428     return  sizeof(uint8_t) + // link code
00429         sizeof(uint8_t) + // reserved
00430         sizeof(uint16_t); // link message size
00431     }
00432 
00433     TimeVal         _htime;     // hello interval
00434     OlsrTypes::WillType     _willingness;   // willingness-to-forward
00435     LinkBag         _links;     // link tuples
00436 };
00437 
00441 class EtxHelloMessage : public HelloMessage {
00442 public:
00443     EtxHelloMessage()
00444     { this->set_type(OlsrTypes::LQ_HELLO_MESSAGE); }
00445     ~EtxHelloMessage() {}
00446 
00447 protected:
00448     size_t decode_link_tuple(uint8_t* buf, size_t& len,
00449                  size_t& skiplen, bool has_lq = true)
00450     throw(InvalidLinkTuple)
00451     {
00452     // Overriding a virtual with default arguments means the signatures
00453     // have to match. We are invoked via a pointer.
00454     return HelloMessage::decode_link_tuple(buf, len, skiplen, has_lq);
00455     }
00456 
00457     inline void add_link(const LinkCode code,
00458              const IPv4& remote_addr,
00459              const double& near_etx,
00460              const double& far_etx) {
00461     HelloMessage::add_link(code,
00462                    LinkAddrInfo(remote_addr, near_etx,
00463                         far_etx));
00464     }
00465 };
00466 
00470 class MidMessage : public Message {
00471 public:
00472     MidMessage()
00473     { this->set_type(OlsrTypes::MID_MESSAGE); }
00474     ~MidMessage() {}
00475 
00476     Message* decode(uint8_t* buf, size_t& len) throw(InvalidMessage);
00477 
00478     bool encode(uint8_t* buf, size_t& len);
00479 
00480     inline size_t   length() const {
00481     return  get_common_header_length() +
00482         (_interfaces.size() * IPv4::addr_bytelen());
00483     }
00484 
00485     inline void add_interface(const IPv4& addr) {
00486     _interfaces.push_back(addr);
00487     }
00488 
00489     inline void clear() { _interfaces.clear(); }
00490 
00491     inline const vector<IPv4>& interfaces() const { return _interfaces; }
00492 
00493     string str() const;
00494 
00495 private:
00496     vector<IPv4>    _interfaces;
00497 };
00498 
00502 class TcMessage : public Message {
00503 public:
00504     TcMessage() { this->set_type(OlsrTypes::TC_MESSAGE); }
00505     ~TcMessage() {}
00506 
00507     virtual Message* decode(uint8_t* buf, size_t& len) throw(InvalidMessage);
00508     bool encode(uint8_t* buf, size_t& len);
00509 
00510     inline size_t   length() const {
00511     return  get_common_header_length() +
00512         sizeof(uint16_t) +  // ANSN
00513         sizeof(uint16_t) +  // Reserved
00514         ( _neighbors.size() * sizeof(uint32_t)); // Neighbor
00515     }
00516 
00517     static inline size_t min_length() {
00518     return  get_common_header_length() +
00519         sizeof(uint16_t) +  // ANSN
00520         sizeof(uint16_t);   // Reserved
00521     }
00522 
00523     inline uint16_t ansn() const { return _ansn; }
00524     inline const vector<LinkAddrInfo>&  neighbors() const {
00525     return _neighbors;
00526     }
00527 
00528     inline void add_neighbor(const IPv4& remote_addr) {
00529     add_neighbor(LinkAddrInfo(remote_addr));
00530     }
00531 
00532     inline size_t remove_neighbor(const IPv4& remote_addr) {
00533     size_t removed_count = 0;
00534     vector<LinkAddrInfo>::iterator ii = _neighbors.begin();
00535     while (ii != _neighbors.end()) {
00536         if ((*ii).remote_addr() == remote_addr) {
00537         ii = _neighbors.erase(ii);
00538         ++removed_count;
00539         } else {
00540         ++ii;
00541         }
00542     }
00543     return removed_count;
00544     }
00545 
00546     inline void set_ansn(uint16_t ansn) { _ansn = ansn; }
00547 
00548     inline void clear() { _neighbors.clear(); _ansn = 0; }
00549 
00550     inline string str() const {
00551     string str = this->common_str();
00552     str += c_format("TC ansn %u ", XORP_UINT_CAST(ansn()));
00553     if (!_neighbors.empty()) {
00554         vector<LinkAddrInfo>::const_iterator ii;
00555         for (ii = _neighbors.begin(); ii != _neighbors.end(); ii++)
00556         str += (*ii).str() + " ";
00557     }
00558     return (str += '\n');
00559     }
00560 
00561 protected:
00562     inline void add_neighbor(const LinkAddrInfo& lai) {
00563     _neighbors.push_back(lai);
00564     }
00565 
00566     void decode_tc_common(uint8_t* buf, size_t& len, bool has_lq = false)
00567     throw(InvalidMessage);
00568 
00569 private:
00570     uint16_t            _ansn;  // advertised neighbor sequence no.
00571     vector<LinkAddrInfo>    _neighbors; // advertised neighbor set.
00572 };
00573 
00577 class EtxTcMessage : public TcMessage {
00578 public:
00579     EtxTcMessage() { this->set_type(OlsrTypes::LQ_TC_MESSAGE); }
00580     ~EtxTcMessage() {}
00581 
00582     inline void add_neighbor(const IPv4& remote_addr,
00583                  const double& near_etx,
00584                  const double& far_etx) {
00585     TcMessage::add_neighbor(LinkAddrInfo(remote_addr, near_etx, far_etx));
00586     }
00587 
00588     Message* decode(uint8_t* buf, size_t& len) throw(InvalidMessage);
00589 };
00590 
00594 class HnaMessage : public Message {
00595 public:
00596     HnaMessage()
00597     { this->set_type(OlsrTypes::HNA_MESSAGE); }
00598     ~HnaMessage() {}
00599 
00600     Message* decode(uint8_t* buf, size_t& len) throw(InvalidMessage);
00601     bool encode(uint8_t* buf, size_t& len);
00602 
00603     inline size_t   length() const {
00604     return  get_common_header_length() +
00605         (_networks.size() *
00606          (sizeof(uint32_t) +    // network address
00607           sizeof(uint32_t)));   // network mask
00608     }
00609 
00610     inline const vector<IPv4Net>& networks() const { return _networks; }
00611 
00612     inline void add_network(const IPv4Net& network) {
00613     _networks.push_back(network);
00614     }
00615 
00616     inline size_t remove_network(const IPv4Net& network) {
00617     size_t removed_count = 0;
00618     vector<IPv4Net>::iterator ii = _networks.begin();
00619     while (ii != _networks.end()) {
00620         if ((*ii) == network) {
00621         ii = _networks.erase(ii);
00622         ++removed_count;
00623         } else {
00624         ++ii;
00625         }
00626     }
00627     return removed_count;
00628     }
00629 
00630     inline void clear() { _networks.clear(); }
00631 
00632     inline string str() const {
00633     string str = this->common_str();
00634     str += "HNA ";
00635     if (!_networks.empty()) {
00636         vector<IPv4Net>::const_iterator ii;
00637         for (ii = _networks.begin(); ii != _networks.end(); ii++)
00638         str += ii->str() + " ";
00639     }
00640     return (str += "\n");
00641     }
00642 
00643 private:
00644     vector<IPv4Net> _networks;
00645 };
00646 
00653 class UnknownMessage : public Message {
00654 public:
00655     Message* decode(uint8_t* buf, size_t& len) throw(InvalidMessage);
00656 
00657     bool encode(uint8_t* buf, size_t& len);
00658 
00659     inline size_t   length() const { return _msg.size(); }
00660 
00661     inline vector<uint8_t> opaque_data() { return this->_msg; }
00662 
00663     inline string str() const {
00664     string str = this->common_str() + "bytes ";
00665     vector<uint8_t>::const_iterator ii;
00666     for (ii = _msg.begin(); ii != _msg.end(); ii++)
00667         str += c_format("0x%0x ", *ii);
00668     return (str += '\n');
00669     }
00670 
00671 private:
00672     size_t  _opaque_data_offset;
00673 };
00674 
00684 class MessageDecoder {
00685 public:
00686     ~MessageDecoder();
00687 
00688     Message* decode(uint8_t* ptr, size_t len) throw(InvalidMessage);
00689 
00690     void register_decoder(Message* message);
00691 
00692 private:
00693     map<OlsrTypes::MessageType, Message* >  _olsrv1;
00694     UnknownMessage              _olsrv1_unknown;
00695 };
00696 
00704 class Packet {
00705 public:
00706     Packet(MessageDecoder& md, OlsrTypes::FaceID faceid = 0)
00707      : _message_decoder(md),
00708        _is_valid(false),
00709        _faceid(faceid),
00710        _seqno(0),
00711        _mtu(0)
00712     {}
00713 
00714     ~Packet() {}
00715 
00716     static size_t get_packet_header_length() {
00717     return  sizeof(uint16_t) +  // packet length
00718         sizeof(uint16_t);   // packet sequence number
00719     }
00720 
00724     size_t length() const;
00725 
00730     size_t mtu_bound() const;
00731 
00737     size_t bounded_length() const;
00738 
00739     void decode(uint8_t* ptr, size_t len) throw(InvalidPacket);
00740 
00749     size_t decode_packet_header(uint8_t* ptr, size_t len)
00750     throw(InvalidPacket);
00751 
00755     bool encode(vector<uint8_t>& pkt);
00756     void update_encoded_seqno(vector<uint8_t>& pkt);
00757 
00758     inline uint16_t seqno() const { return _seqno; }
00759     inline void set_seqno(uint16_t seqno) { _seqno = seqno; }
00760 
00761     inline OlsrTypes::FaceID    faceid() const
00762     { return _faceid; }
00763 
00764     inline uint32_t mtu() const { return _mtu; }
00765     inline void set_mtu(const uint32_t mtu) { _mtu = mtu; }
00766 
00767     inline void set_faceid(OlsrTypes::FaceID faceid)
00768     { _faceid = faceid; }
00769 
00773     string str() const;
00774 
00775     inline void add_message(Message* m) {
00776     _messages.push_back(m);
00777     }
00778 
00779     inline void clear() {
00780     _seqno = 0;
00781     _mtu = 0;
00782     _messages.clear();
00783     _is_valid = false;
00784     }
00785 
00786     inline const vector<Message*>& messages() { return _messages; }
00787 
00794     inline vector<Message*>& get_messages() { return _messages; }
00795 
00796     bool valid() const { return _is_valid; }
00797 
00798     vector<uint8_t>& get() { return _pkt; }
00799 
00800     void store(uint8_t* ptr, size_t len) {
00801     _pkt.resize(len);
00802     memcpy(&_pkt[0], ptr, len);
00803     }
00804 
00805 private:
00806     MessageDecoder& _message_decoder;
00807     bool        _is_valid;
00808     OlsrTypes::FaceID   _faceid;    // interface where this was received
00809     uint16_t        _seqno;
00810     uint32_t        _mtu;       // maximum transmission unit
00811     vector<Message*>    _messages;  // messages this packet contains.
00812     vector<uint8_t> _pkt;       // on-wire packet data.
00813 };
00814 
00815 inline
00816 void
00817 initialize_message_decoder(MessageDecoder& message_decoder)
00818 {
00819     //
00820     // NOTE: Do not register UnknownMessage explicitly -- it has no
00821     // type field to match. It is deliberately used from the message
00822     // parser so that we will forward opaque messages as per the OLSR RFC.
00823     //
00824     message_decoder.register_decoder(new HelloMessage());
00825     message_decoder.register_decoder(new TcMessage());
00826     message_decoder.register_decoder(new MidMessage());
00827     message_decoder.register_decoder(new HnaMessage());
00828 #ifdef notyet
00829     message_decoder.register_decoder(new EtxHelloMessage());
00830     message_decoder.register_decoder(new EtxTcMessage());
00831 #endif
00832 }
00833 
00834 #endif // __OLSR_MESSAGE_HH__
 All Classes Namespaces Functions Variables Typedefs Enumerations