Wiselib
wiselib.testing/algorithms/routing/flooding/flooding_algorithm.h
Go to the documentation of this file.
00001 /***************************************************************************
00002  ** This file is part of the generic algorithm library Wiselib.           **
00003  ** Copyright (C) 2008,2009 by the Wisebed (www.wisebed.eu) project.      **
00004  **                                                                       **
00005  ** The Wiselib is free software: you can redistribute it and/or modify   **
00006  ** it under the terms of the GNU Lesser General Public License as        **
00007  ** published by the Free Software Foundation, either version 3 of the    **
00008  ** License, or (at your option) any later version.                       **
00009  **                                                                       **
00010  ** The Wiselib 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 Lesser General Public License for more details.                   **
00014  **                                                                       **
00015  ** You should have received a copy of the GNU Lesser General Public      **
00016  ** License along with the Wiselib.                                       **
00017  ** If not, see <http://www.gnu.org/licenses/>.                           **
00018  ***************************************************************************/
00019 #ifndef __FLOODING_ALGORITHM_H__
00020 #define __FLOODING_ALGORITHM_H__
00021 
00022 #include "util/base_classes/routing_base.h"
00023 #include "flooding_message.h"
00024 #include <string.h>
00025 
00026 namespace wiselib
00027 {
00028 
00036    template<typename OsModel_P,
00037             typename NodeidIntMap_P,
00038             typename Radio_P = typename OsModel_P::Radio,
00039             typename Debug_P = typename OsModel_P::Debug>
00040    class FloodingAlgorithm
00041       : public RoutingBase<OsModel_P, Radio_P>
00042    {
00043    public:
00044       typedef OsModel_P OsModel;
00045       typedef Radio_P Radio;
00046       typedef Debug_P Debug;
00047 
00048       typedef NodeidIntMap_P MapType;
00049       typedef typename MapType::iterator MapTypeIterator;
00050 
00051       typedef FloodingAlgorithm<OsModel, MapType, Radio, Debug> self_type;
00052       typedef self_type* self_pointer_t;
00053 
00054       typedef typename Radio::node_id_t node_id_t;
00055       typedef typename Radio::size_t size_t;
00056       typedef typename Radio::block_data_t block_data_t;
00057       typedef typename Radio::message_id_t message_id_t;
00058 
00059       typedef FloodingMessage<OsModel, Radio> Message;
00060       // --------------------------------------------------------------------
00061       enum ErrorCodes
00062       {
00063          SUCCESS = OsModel::SUCCESS,
00064          ERR_UNSPEC = OsModel::ERR_UNSPEC,
00065          ERR_NETDOWN = OsModel::ERR_NETDOWN
00066       };
00067       // --------------------------------------------------------------------
00068       enum SpecialNodeIds
00069       {
00070          BROADCAST_ADDRESS = Radio_P::BROADCAST_ADDRESS, 
00071          NULL_NODE_ID      = Radio_P::NULL_NODE_ID      
00072       };
00073       // --------------------------------------------------------------------
00074       enum Restrictions
00075       {
00076          MAX_MESSAGE_LENGTH = Radio_P::MAX_MESSAGE_LENGTH - Message::PAYLOAD_POS  
00077       };
00078       // --------------------------------------------------------------------
00081       FloodingAlgorithm();
00082       ~FloodingAlgorithm();
00084 
00087       int enable_radio( void );
00088       int disable_radio( void );
00090 
00093 
00095       int send( node_id_t receiver, size_t len, block_data_t *data );
00098       void receive( node_id_t from, size_t len, block_data_t *data );
00101       typename Radio::node_id_t id()
00102       { return radio_->id(); };
00104 
00105       int init( Radio& radio, Debug& debug )
00106       {
00107          radio_ = &radio;
00108          debug_ = &debug;
00109          return SUCCESS;
00110       }
00111 
00112       int init()
00113       {
00114          seq_nr_ = FLOODING_INIT_SEQ_NR;
00115          return enable_radio();
00116       }
00117 
00118       int destruct()
00119       {
00120          return disable_radio();
00121       }
00122 
00123    private:
00124       Radio& radio()
00125       { return *radio_; }
00126 
00127       Debug& debug()
00128       { return *debug_; }
00129 
00130       typename Radio::self_pointer_t radio_;
00131       typename Debug::self_pointer_t debug_;
00132 
00133       enum MessageIds
00134       {
00135          FLOODING_MESSAGE_ID = 112
00136       };
00137 
00138       enum SequenceNumbers
00139       {
00140          FLOODING_INIT_SEQ_NR = 0
00141       };
00142 
00143       int callback_id_;
00144       uint16_t seq_nr_;
00145 
00146       MapType seq_map_;
00147    };
00148    // -----------------------------------------------------------------------
00149    // -----------------------------------------------------------------------
00150    // -----------------------------------------------------------------------
00151    template<typename OsModel_P,
00152             typename RoutingTable_P,
00153             typename Radio_P,
00154             typename Debug_P>
00155    FloodingAlgorithm<OsModel_P, RoutingTable_P, Radio_P, Debug_P>::
00156    FloodingAlgorithm()
00157       : callback_id_ ( 0 ),
00158          seq_nr_     ( FLOODING_INIT_SEQ_NR )
00159    {}
00160    // -----------------------------------------------------------------------
00161    template<typename OsModel_P,
00162             typename RoutingTable_P,
00163             typename Radio_P,
00164             typename Debug_P>
00165    FloodingAlgorithm<OsModel_P, RoutingTable_P, Radio_P, Debug_P>::
00166    ~FloodingAlgorithm()
00167    {
00168 #ifdef ROUTING_FLOODING_DEBUG
00169       debug().debug( "FloodingAlgorithm:dtor\n" );
00170 #endif
00171    }
00172    // -----------------------------------------------------------------------
00173    template<typename OsModel_P,
00174             typename RoutingTable_P,
00175             typename Radio_P,
00176             typename Debug_P>
00177    int
00178    FloodingAlgorithm<OsModel_P, RoutingTable_P, Radio_P, Debug_P>::
00179    enable_radio( void )
00180    {
00181 #ifdef ROUTING_FLOODING_DEBUG
00182       debug().debug( "FloodingAlgorithm: Boot for %i\n", radio().id() );
00183 #endif
00184 
00185       radio().enable_radio();
00186       callback_id_ = radio().template reg_recv_callback<self_type, &self_type::receive>( this );
00187       return SUCCESS;
00188    }
00189    // -----------------------------------------------------------------------
00190    template<typename OsModel_P,
00191             typename RoutingTable_P,
00192             typename Radio_P,
00193             typename Debug_P>
00194    int
00195    FloodingAlgorithm<OsModel_P, RoutingTable_P, Radio_P, Debug_P>::
00196    disable_radio( void )
00197    {
00198 #ifdef ROUTING_FLOODING_DEBUG
00199       debug().debug( "FloodingAlgorithm: Disable\n" );
00200 #endif
00201       radio().unreg_recv_callback( callback_id_ );
00202       radio().disable();
00203       return SUCCESS;
00204    }
00205    // -----------------------------------------------------------------------
00206    template<typename OsModel_P,
00207             typename RoutingTable_P,
00208             typename Radio_P,
00209             typename Debug_P>
00210    int
00211    FloodingAlgorithm<OsModel_P, RoutingTable_P, Radio_P, Debug_P>::
00212    send( node_id_t destination, size_t len, block_data_t *data )
00213    {
00214 #ifdef ROUTING_FLOODING_DEBUG
00215       debug().debug( "FloodingAlgorithm: Send at %d\n", radio_->id() );
00216 #endif
00217 
00218       Message message;
00219       message.set_msg_id( FLOODING_MESSAGE_ID );
00220       message.set_node_id( radio().id() );
00221       message.set_seq_nr( seq_nr_ );
00222       message.set_payload( len, data );
00223 
00224       radio().send( radio().BROADCAST_ADDRESS, message.buffer_size(), (block_data_t*)&message );
00225 
00226       seq_nr_++;
00227       return SUCCESS;
00228    }
00229    // -----------------------------------------------------------------------
00230    template<typename OsModel_P,
00231             typename RoutingTable_P,
00232             typename Radio_P,
00233             typename Debug_P>
00234    void
00235    FloodingAlgorithm<OsModel_P, RoutingTable_P, Radio_P, Debug_P>::
00236    receive( node_id_t from, size_t len, block_data_t *data )
00237    {
00238 
00239       if ( from == radio().id() )
00240       {
00241 #ifdef ROUTING_FLOODING_DEBUG
00242    debug().debug( "FloodingAlgorithm ERROR: received radio message from myself at %u\n", radio_->id() );
00243 #endif
00244          return;
00245       }
00246 
00247 
00248       message_id_t msg_id = read<OsModel, block_data_t, message_id_t>( data );
00249 
00250       if ( msg_id == FLOODING_MESSAGE_ID )
00251       {
00252          Message *message = (Message *)data;
00253          if ( message->node_id() == radio().id() )
00254          {
00255 #ifdef ROUTING_FLOODING_DEBUG
00256    debug().debug( "FloodingAlgorithm ERROR: received flooding message from myself at %u (msg id is %u)\n", radio_->id(), message->node_id() );
00257 #endif
00258             return;
00259          }
00260 
00261          // Has message already been received? If so, return.
00262          // Of course, there is a simplification with the check for seq_nr
00263          // just to be greater than the known one---but this can be done for
00264          // simplicity reasons (code-space!!)
00265          MapTypeIterator it = seq_map_.find( message->node_id() );
00266          if ( it == seq_map_.end() ||
00267                ( it != seq_map_.end() &&
00268                   ( message->seq_nr() > it->second ||
00269                   ( message->seq_nr() == FLOODING_INIT_SEQ_NR && it->second >= 2))) )
00270          {
00271             // Update sequence number, and forward the message to neighbors.
00272             seq_map_[message->node_id()] = message->seq_nr();
00273             radio().send( radio().BROADCAST_ADDRESS, len, data );
00274 
00275 #ifdef ROUTING_FLOODING_DEBUG
00276             debug().debug( "FloodingAlgorithm: receive at %d from %d with seqnr %d (here is %d)\n",
00277                            radio_->id(), message->node_id(), message->seq_nr(), seq_map_[message->node_id()] );
00278 #endif
00279 
00280             // Pass message to each registered receiver.
00281             notify_receivers( message->node_id(), message->payload_size(), message->payload() );
00282          }
00283          else
00284          {
00285 #ifdef ROUTING_FLOODING_DEBUG
00286    debug().debug( "FloodingAlgorithm ERROR: sequence number already known at %d (%d <= %d)\n",
00287                      radio_->id(), message->seq_nr(), seq_map_[message->node_id()]  );
00288 #endif
00289          }
00290       }
00291       else
00292       {
00293 #ifdef ROUTING_FLOODING_DEBUG
00294    debug().debug( "FloodingAlgorithm INFO: unknown message at %d (%d != %d)\n", radio_->id(), msg_id, FLOODING_MESSAGE_ID );
00295 #endif
00296       }
00297    }
00298 
00299 }
00300 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines