rreq_buffer.c

00001 /* Copyright 2008 Michael Marsh, University of Maryland.
00002  *
00003  * This file is part of pydtn.
00004  *
00005  * pydtn is free software: you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation, either version 3 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * pydtn 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 pydtn.  If not, see <http://www.gnu.org/licenses/>.
00017  *
00018  * The views and conclusions contained in the software and documentation
00019  * are those of the authors and should not be interpreted as representing
00020  * official policies, either expressed or implied, of the University
00021  * of Maryland.
00022  *
00023  * pydtn extends and embeds the Python interpreter, which is
00024  * Copyright 2001-2006 Python Software Foundation, All Rights Reserved,
00025  * and is released under the PSF License Agreement.
00026  *
00027  * RANLUX random number generation uses the Boost library,
00028  * Copyright 1994-2006 by various authors (details in individual files),
00029  * which is released under the Boost Software License, Version 1.0.
00030  */
00031 
00032 #include "aodv.h"
00033 
00034 static void
00035 _buffer_rreq_base( aodv_rreq_t** buffer,
00036                    aodv_rreq_t* rreq,
00037                    unsigned int timeout )
00038 {
00039    aodv_rreq_t* head = NULL;
00040    aodv_rreq_t* tail = NULL;
00041    struct timeval* tv = NULL;
00042 
00043    if ( NULL == buffer ) return;
00044    if ( NULL == rreq ) return;
00045 
00046    if ( NULL == *buffer )
00047    {
00048       rreq->next = rreq;
00049       rreq->prev = rreq;
00050       *buffer = rreq;
00051    }
00052    else
00053    {
00054       head = *buffer;
00055       tail = head->prev;
00056       rreq->next = head;
00057       rreq->prev = tail;
00058       tail->next = rreq;
00059       head->prev = rreq;
00060    }
00061 
00062    tv = &(rreq->buffer_time);
00063    aodv_gettime(tv);
00064    tv->tv_usec += 1000 * timeout;
00065    while ( tv->tv_usec >= 1000000 )
00066    {
00067       tv->tv_usec -= 1000000;
00068       tv->tv_sec += 1;
00069    }
00070    rreq->ntries = 1;
00071 }
00072 
00073 void
00074 buffer_aodv_rreq( aodv_state_t* state, aodv_rreq_t* rreq )
00075 {
00076    _buffer_rreq_base( &(state->rreq_buffer),
00077                       rreq,
00078                       state->params.net_traversal_time );
00079 }
00080 
00081 void
00082 buffer_rcvd_aodv_rreq( aodv_state_t* state, aodv_rreq_t* rreq )
00083 {
00084    _buffer_rreq_base( &(state->rcvd_rreq_buffer),
00085                       rreq,
00086                       state->params.path_discovery_time );
00087 }
00088 
00089 
00090 static aodv_rreq_t*
00091 _unbuffer_rreq_base( aodv_rreq_t** buffer, aodv_rreq_t* rreq )
00092 {
00093    aodv_rreq_t* head;
00094    aodv_rreq_t* tail;
00095    aodv_rreq_t* retval = NULL;
00096    char is_head = 0;
00097    char is_tail = 0;
00098 
00099    if ( NULL == buffer ) return NULL;
00100    if ( NULL == *buffer ) return NULL;
00101    if ( NULL == rreq ) return NULL;
00102 
00103    head = *buffer;
00104    tail = head->prev;
00105 
00106    if ( rreq == head ) is_head = 1;
00107    if ( rreq == tail ) is_tail = 1;
00108 
00109    if ( is_head && is_tail )
00110    {
00111       retval = NULL;
00112       *buffer = NULL;
00113    }
00114    else if ( is_head )
00115    {
00116       retval = rreq->next;
00117       *buffer = retval;
00118       retval->prev = tail;
00119       tail->next = retval;
00120    }
00121    else if ( is_tail )
00122    {
00123       retval = tail->prev;
00124       head->prev = tail->prev;
00125       tail->prev->next = head;
00126    }
00127    else
00128    {
00129       retval = rreq->next;
00130       rreq->prev->next = rreq->next;
00131       rreq->next->prev = rreq->prev;
00132    }
00133 
00134    free_aodv_rreq( rreq );
00135 
00136    return retval;
00137 }
00138 
00139 aodv_rreq_t*
00140 unbuffer_aodv_rreq( aodv_state_t* state, aodv_rreq_t* rreq )
00141 {
00142    if ( NULL == state ) return NULL;
00143    if ( NULL == state->rreq_buffer ) return NULL;
00144    if ( NULL == rreq ) return NULL;
00145 
00146    return _unbuffer_rreq_base( &(state->rreq_buffer), rreq );
00147 }
00148 
00149 aodv_rreq_t*
00150 unbuffer_rcvd_aodv_rreq( aodv_state_t* state, aodv_rreq_t* rreq )
00151 {
00152    if ( NULL == state ) return NULL;
00153    if ( NULL == state->rcvd_rreq_buffer ) return NULL;
00154    if ( NULL == rreq ) return NULL;
00155 
00156    return _unbuffer_rreq_base( &(state->rcvd_rreq_buffer), rreq );
00157 }
00158 
00159 
00160 /*
00161  * This routine does double duty: check for the rreq in the buffer
00162  * and clean out expired entries.  This is lazy garbage collection.
00163  *
00164  */
00165 static int
00166 _is_buffered_rreq_base( aodv_rreq_t** buffer, const aodv_rreq_t* rreq )
00167 {
00168    aodv_rreq_t* head;
00169    aodv_rreq_t* curr;
00170    int retval = 0;
00171 
00172    if ( NULL == buffer ) return 0;
00173    if ( NULL == *buffer ) return 0;
00174    if ( NULL == rreq ) return 0;
00175 
00176    head = *buffer;
00177    curr = head;
00178    do
00179    {
00180       if ( aodv_pasttime( &(curr->buffer_time) ) )
00181       {
00182          curr = _unbuffer_rreq_base( buffer, curr );
00183          head = *buffer;
00184       }
00185 
00186       if ( NULL != curr )
00187       {
00188          if ( ( 0 == retval ) &&
00189               ( 0 == aodv_cmp_addr( &(curr->originator),
00190                                     &(rreq->originator) ) ) &&
00191               ( curr->rreq_id == rreq->rreq_id ) )
00192          {
00193             retval = 1;
00194          }
00195          curr = curr->next;
00196       }
00197    } while ( curr != head );
00198 
00199    return retval;
00200 }
00201 
00202 int
00203 is_buffered_aodv_rreq( aodv_state_t* state, aodv_rreq_t* rreq )
00204 {
00205    if ( NULL == state ) return 0;
00206    if ( NULL == state->rreq_buffer ) return 0;
00207    if ( NULL == rreq ) return 0;
00208 
00209    return _is_buffered_rreq_base( &(state->rreq_buffer), rreq );
00210 }
00211 
00212 int
00213 is_buffered_rcvd_aodv_rreq( aodv_state_t* state, aodv_rreq_t* rreq )
00214 {
00215    if ( NULL == state ) return 0;
00216    if ( NULL == state->rcvd_rreq_buffer ) return 0;
00217    if ( NULL == rreq ) return 0;
00218 
00219    return _is_buffered_rreq_base( &(state->rcvd_rreq_buffer), rreq );
00220 }
00221 
00222 aodv_rreq_t*
00223 find_buffered_aodv_rreq( aodv_state_t* state, const aodv_addr_t* dest )
00224 {
00225    aodv_rreq_t* head;
00226    aodv_rreq_t* curr;
00227 
00228    if ( NULL == state ) return NULL;
00229    if ( NULL == state->rreq_buffer ) return NULL;
00230 
00231    head = state->rreq_buffer;
00232    curr = head;
00233    do
00234    {
00235       if ( 0 == aodv_cmp_addr( &(curr->destination), dest ) ) return curr;
00236       curr = curr->next;
00237    } while ( curr != head );
00238    return NULL;
00239 }

Generated on Mon Mar 24 11:15:45 2008 for Pydtn Simulator by  doxygen 1.5.4