packet.hxx

Go to the documentation of this file.
00001 // Copyright (C) 2003-2006 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,
00018 // Boston, MA  02110-1301, USA.
00019 
00020 #ifndef QOLYESTER_DAEMON_PKT_PACKET_HXX
00021 # define QOLYESTER_DAEMON_PKT_PACKET_HXX 1
00022 
00023 # include "alg/mainaddrof.hh"
00024 # include "set/neighbors.hh"
00025 
00026 # include "pkt/packet.hh"
00027 
00028 namespace olsr {
00029 
00030   extern cproxy_t       cproxy;
00031 
00032   namespace pkt {
00033 
00034     // Packet sequence number
00035     std::map<address_t, utl::Seqnum<u_int16_t> >
00036     Packet::seqnum_map = std::map<address_t, utl::Seqnum<u_int16_t> >();
00037 
00038     // Ctor for locally generated packets.  The first parameter is the
00039     // maximum size of the packet and the second is the interface on
00040     // which we wish to send it.
00041     Packet::Packet(const ::size_t mtu, const address_t& addr) :
00042       _size(sizeof (raw)),
00043       _sender(addr),
00044 # ifdef QOLYESTER_ENABLE_VIRTUAL
00045         // we must allocate size to put an IP address in header
00046       _data(mtu+address_t::address_size),
00047       _raw()
00048 # else // !QOLYESTER_ENABLE_VIRTUAL
00049       _data(mtu),
00050       _raw(reinterpret_cast<raw*>(_data.raw()))
00051 # endif
00052     {
00053 # ifdef QOLYESTER_ENABLE_VIRTUAL
00054         // add in header source IP address
00055       addr.dump(_data.raw());
00056         // we must modify the size here (to add messages after)
00057       _size+=address_t::address_size;
00058       _raw=reinterpret_cast<raw*>((_data+address_t::address_size).raw());
00059 # endif
00060       assert(mtu >= min_length);
00061       _raw->seqnum = 0;
00062     }
00063 
00064     // Ctor for received packets.  The first argument is the sender of
00065     // the packet and the second is the buffer with the received data.
00066     Packet::Packet(const address_t& addr, const utl::Data& d) :
00067       _size(d.size()),
00068       _sender(addr),
00069       _data(d),
00070       _raw(reinterpret_cast<raw*>(_data.raw()))
00071     {}
00072 
00073     // Simple proxy method to add a message.
00074     // FIXME: is that really necessary?
00075     bool
00076     Packet::add_message(const msg::Message& m) {
00077       utl::Data d(_data + _size);
00078       bool      ret = m.dump(d, _sender);
00079       _size = _data - d;
00080       return ret;
00081     }
00082 
00083     void
00084     Packet::close(const address_t& i) {
00085       _data.fit(_size);
00086 # ifdef QOLYESTER_ENABLE_VIRTUAL
00087         // say in the header that the size is (address_size) less
00088       _raw->length = htons(_size-address_t::address_size);
00089 # else
00090       _raw->length = htons(_size);
00091 # endif
00092 
00093       if (_size > min_length)
00094         _raw->seqnum = htons(seqnum_map[i]++);
00095     }
00096 
00097     // Packet parsing routine.
00098     void
00099     Packet::parse(utl::Data d,
00100                   const address_t& sender,
00101                   const address_t& receiver) {
00102       // Ignore locally generated packets.
00103       if (alg::main_addr_of(sender) == main_addr)
00104         return;
00105 
00106       // Check if there is too little data to ever hold any message.
00107       if (d.size() < Packet::min_length + msg::Message::min_length) {
00108         warning << "Packet::parse(): Short packet from " << sender
00109                 << std::endl;
00110         return;
00111       }
00112 
00113       // Extract the packet header.
00114       const raw*        pheader = reinterpret_cast<const raw*>(d.raw());
00115 
00116       // Check if there the actual data size is the same as packet length.
00117       if ((unsigned short)(ntohs(pheader->length)) != d.size()) {
00118         warning << "Packet::parse(): Packet length mismatch from " << sender
00119                 << ' ' << ntohs(pheader->length) << " != " << d.size()
00120                 << std::endl;
00121         return;
00122       }
00123 
00124       seqnum_t  pseqnum(ntohs(pheader->seqnum));
00125 
00126 # ifdef QOLYESTER_ENABLE_LINKHYS
00127       // This is done to decrease link quality on packet loss.
00128 
00129       // The 1-hop neighbor set is updated once the messages have been
00130       // processed, in order to avoid breaking link symmetry if this
00131       // packet contains a HELLO message that would increase the
00132       // quality.
00133       cproxy_t::linkset_t::iterator     x =
00134         cproxy.linkset().find(set::Link::make_key(receiver, sender));
00135 
00136       if (x != cproxy.linkset().end())
00137         x->set_last_seqnum(pseqnum);
00138 # endif
00139 
00140       // Parsing messages
00141 
00142       utl::Data payload = d + sizeof (raw);
00143 
00144       while (payload.size() > 0) {
00145         // Extract message header.
00146         const msg::Message::raw*        mheader =
00147           reinterpret_cast<const msg::Message::raw*>(payload.raw());
00148 
00149         // Check that a message header fits.
00150         if (payload.size() < msg::Message::min_length) {
00151           warning << "Packet::parse(): Short message from " << sender
00152                   << std::endl;
00153           break;
00154         }
00155 
00156         // Check that this message fits.
00157         if (payload.size() < (unsigned short)(ntohs(mheader->size))) {
00158           warning << "Packet::parse(): Truncated message from " << sender
00159                   << std::endl;
00160           break;
00161         }
00162 
00163         // Check that the message is not funny.
00164         if ((u_int16_t)(ntohs(mheader->size)) < msg::Message::min_length) {
00165           warning << "Packet::parse(): corrupted message header from "
00166                   << sender << std::endl;
00167           break;
00168         }
00169 
00170         // Parse the message.
00171         msg::Message::parse(payload.shrink_to(ntohs(mheader->size)),
00172                             sender, receiver, pseqnum);
00173 
00174         payload += ntohs(mheader->size);
00175       }
00176 
00177 # ifdef QOLYESTER_ENABLE_LINKHYS
00178       // Try to find the link again, since the current packet could
00179       // contain a HELLO message.
00180       if (x == cproxy.linkset().end())
00181         x = cproxy.linkset().find(set::Link::make_key(receiver, sender));
00182 
00183       if (x != cproxy.linkset().end()) {
00184         x->set_nexttime(timeval_t::in(x->htime() * cst::hello_grace));
00185 
00186         typedef set::upd::LinkUpdater   lu_t;
00187 
00188         sch::TimedEvent*        e = x->updater();
00189 
00190         assert(e != 0);
00191         scheduler.erase(e);
00192         e->set_next(lu_t::min_time(*x));
00193         scheduler.insert(e);
00194       }
00195 # endif
00196 
00197     }
00198 
00199   } // namespace pkt
00200 
00201 } // namespace olsr
00202 
00203 #endif // ! QOLYESTER_DAEMON_PKT_PACKET_HXX

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