Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

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

Generated on Thu Jul 28 21:21:48 2005 for Qolyester daemon by  doxygen 1.4.1