message.hxx

Go to the documentation of this file.
00001 // Copyright (C) 2003, 2004, 2005 Laboratoire de Recherche en Informatique
00002 
00003 // This file is part of Qolyester.
00004 
00005 // Qolyester is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 
00010 // Qolyester is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018 
00019 #ifndef QOLYESTER_DAEMON_MSG_MESSAGE_HXX
00020 # define QOLYESTER_DAEMON_MSG_MESSAGE_HXX 1
00021 
00022 # include "utl/vtime.hh"
00023 # include "set/duplicate.hh"
00024 # include "sch/events.hh"
00025 # include "msg/hello.hh"
00026 # include "msg/hna.hh"
00027 # include "msg/mid.hh"
00028 # include "msg/tc.hh"
00029 
00030 # include "message.hh"
00031 
00032 namespace olsr {
00033 
00034   namespace msg {
00035 
00036     // Message parsing routine.
00037     void
00038     Message::parse(utl::Data d,
00039                    const address_t& sender,
00040                    const address_t& receiver,
00041                    const seqnum_t& pseqnum) {
00042 
00043       // Extract the header.
00044       raw*      h = reinterpret_cast<raw*>(d.raw());
00045 
00046       if (h->ttl == 0)
00047         return;
00048 
00049       // Extract the originator's address from the header.
00050       address_t         orig(h->addr, ADDRESS_SIZE);
00051 
00052       // Discard the message if the local node is the originator.
00053       if (orig == main_addr)
00054         return;
00055 
00056       // Check the message size, isolate message content and extract
00057       // validity time.
00058       assert(d.size() == (u_int16_t)(ntohs(h->size)));
00059 
00060       utl::Data         payload = d + sizeof (raw);
00061       timeval_t         validity = utl::Vtime(h->vtime).operator timeval_t();
00062       //      utl::Vtime        validity(h->vtime);
00063 
00064       seqnum_t          seqnum(ntohs(h->seqnum));
00065 
00066       header    mh(sender, receiver, orig, validity,
00067                    pseqnum, seqnum, h->hopcount);
00068 
00069       // If the message is a HELLO message, parse it right away.
00070       if (h->type == HELLO_MESSAGE) {
00071         HELLOMessage::parse(payload, mh);
00072         return;
00073       }
00074 
00075       // Check that the message is not a duplicate.
00076       dupset_t::dupset_t::iterator      x =
00077         dup_set.dupset().find(set::DuplicateEntry::make_key(orig, seqnum));
00078 
00079       if (x == dup_set.dupset().end()) {
00080         // The message is not a duplicate.
00081         // We have to process the message.
00082         // Dispatch the message to its rightful parser.
00083         switch (h->type) {
00084         case HELLO_MESSAGE:
00085           assert(HELLO_MESSAGE != HELLO_MESSAGE);
00086           break;
00087         case TC_MESSAGE:
00088           TCMessage::parse(payload, mh);
00089           break;
00090         case MID_MESSAGE:
00091           MIDMessage::parse(payload, mh);
00092           break;
00093         case HNA_MESSAGE:
00094           HNAMessage::parse(payload, mh);
00095           break;
00096         default:
00097           break;
00098         }
00099 
00100       }
00101 
00102       // Check if we have to forward the message.
00103       if (x == dup_set.dupset().end() || !x->in_ifaces(receiver)) {
00104         // We have to consider the message for forwarding.
00105         // Dispatch to the rightful forwarder.
00106         switch (h->type) {
00107         case HELLO_MESSAGE:
00108           // WE DON'T FORWARD HELLO MESSAGES
00109           // FIXME: This case should never be reached, as we check it
00110           // earlier.
00111           assert(HELLO_MESSAGE != HELLO_MESSAGE);
00112           break;
00113         case TC_MESSAGE:
00114           TCMessage::forward(d, mh);
00115           break;
00116         case MID_MESSAGE:
00117           MIDMessage::forward(d, mh);
00118           break;
00119         case HNA_MESSAGE:
00120           HNAMessage::forward(d, mh);
00121           break;
00122         default:
00123           // Default forwarding algorithm for unknown message types.
00124           Message::forward(d, mh);
00125           break;
00126         }
00127       }
00128     }
00129 
00130     // Default forwarding algorithm
00131     void
00132     Message::forward(utl::Data& d, const header& mh) {
00133       cproxy_t::linkset_t::iterator     lx =
00134         cproxy.linkset().find(set::Link::make_key(mh.receiver, mh.sender));
00135 
00136       // Don't forward the message if the originating interface is not
00137       // part of a symmetric link.
00138       if (lx == cproxy.linkset().end() || !lx->is_sym())
00139         return;
00140 
00141       // Extract message header.
00142       raw*      h = reinterpret_cast<raw*>(d.raw());
00143 
00144       // Look for an entry in the duplicate set with this sequence number.
00145       dupset_t::dupset_t::iterator      dx =
00146         dup_set.dupset().find(set::DuplicateEntry::make_key(mh.originator,
00147                                                             ntohs(h->seqnum)));
00148 
00149       // If the message is a duplicate that has already been processed
00150       // on this interface or has already been retransmitted, discard
00151       // it.
00152       if (dx != dup_set.dupset().end() &&
00153           (dx->retransmitted() || dx->in_ifaces(mh.receiver)))
00154         return;
00155 
00156       // Get the main address of the originating interface.
00157       const address_t&          maddr = alg::main_addr_of(mh.sender);
00158 
00159       // Consider for forwarding only if the originating interface
00160       // belongs to a neighbor that is a MPR-selector.  Also check
00161       // that the TTL is greater than 1.
00162       cproxy_t::sym_neighborset_t::iterator     nx =
00163         cproxy.sym_neighborset().find(set::Neighbor::make_key(maddr));
00164 
00165       bool                      retransmit = false;
00166       if (nx != cproxy.sym_neighborset().end() &&
00167           nx->is_mprsel() &&
00168           h->ttl > 1)
00169         retransmit = true;
00170 
00171       // Update the entry in the duplicate set or insert a new one.
00172       dup_set.insert(set::DuplicateEntry(mh.originator,
00173                                          ntohs(h->seqnum),
00174                                          mh.receiver, retransmit));
00175 
00176       // If the message was not to be forwarded, stop here.
00177       if (!retransmit)
00178         return;
00179 
00180       // Decrement the TTL and increment the hop count.
00181       --h->ttl;
00182       ++h->hopcount;
00183 
00184       // Schedule the packet to be sent.
00185       typedef UnknownMessage            um_t;
00186       typedef sch::MessageForwarder     mf_t;
00187 
00188       scheduler.insert(new mf_t(timeval_t::in_jitter(cst::maxjitter),
00189                                 um_t(d)));
00190     }
00191 
00192     UnknownMessage::UnknownMessage(utl::Data& d) : _data(d) {}
00193 
00194     // Simple dump method for unknown messages.
00195     bool
00196     UnknownMessage::dump(utl::Data& d, const address_t&) const {
00197       if (d.size() < _data.size())
00198         return true;
00199 
00200       _data.dump(d);
00201       d += _data.size();
00202       return false;
00203     }
00204 
00205   } // namespace msg
00206 
00207 } // namespace olsr
00208 
00209 #endif // ! QOLYESTER_DAEMON_MSG_MESSAGE_HXX

Generated on Mon Sep 10 17:02:12 2007 for Qolyester daemon by  doxygen 1.5.1