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

pana_retransmission.h

00001 /* BEGIN_COPYRIGHT                                                        */
00002 /*                                                                        */
00003 /* Open Diameter: Open-source software for the Diameter and               */
00004 /*                Diameter related protocols                              */
00005 /*                                                                        */
00006 /* Copyright (C) 2002-2004 Open Diameter Project                          */
00007 /*                                                                        */
00008 /* This library is free software; you can redistribute it and/or modify   */
00009 /* it under the terms of the GNU Lesser General Public License as         */
00010 /* published by the Free Software Foundation; either version 2.1 of the   */
00011 /* License, or (at your option) any later version.                        */
00012 /*                                                                        */
00013 /* This library is distributed in the hope that it will be useful,        */
00014 /* but WITHOUT ANY WARRANTY; without even the implied warranty of         */
00015 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      */
00016 /* Lesser General Public License for more details.                        */
00017 /*                                                                        */
00018 /* You should have received a copy of the GNU Lesser General Public       */
00019 /* License along with this library; if not, write to the Free Software    */
00020 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307    */
00021 /* USA.                                                                   */
00022 /*                                                                        */
00023 /* In addition, when you copy and redistribute some or the entire part of */
00024 /* the source code of this software with or without modification, you     */
00025 /* MUST include this copyright notice in each copy.                       */
00026 /*                                                                        */
00027 /* If you make any changes that are appeared to be useful, please send    */
00028 /* sources that include the changed part to                               */
00029 /* diameter-developers@lists.sourceforge.net so that we can reflect your  */
00030 /* changes to one unified version of this software.                       */
00031 /*                                                                        */
00032 /* END_COPYRIGHT                                                          */
00033 
00034 #ifndef __PANA_RETRANSMISSION_H__
00035 #define __PANA_RETRANSMISSION_H__
00036 
00037 #include <iostream>
00038 #include <list>
00039 #include "ace/OS.h"
00040 #include "pana_config_manager.h"
00041 
00042 /*
00043    PANA retransmission timers are based on the model used in DHCPv6
00044    [RFC3315].  Variables used here are also borrowed from this
00045    specification.  PANA is a request response like protocol.  The
00046    message exchange terminates when either the request sender
00047    successfully receives the appropriate answer, or when the message
00048    exchange is considered to have failed according to the retransmission
00049    mechanism described below.
00050 
00051    The retransmission behavior is controlled and described by the
00052    following variables:
00053 
00054          RT     Retransmission timeout
00055 
00056          IRT    Initial retransmission time
00057 
00058          MRC    Maximum retransmission count
00059 
00060          MRT    Maximum retransmission time
00061 
00062          MRD    Maximum retransmission duration
00063 
00064          RAND   Randomization factor
00065          
00066    With each message transmission or retransmission, the sender sets RT
00067    according to the rules given below.  If RT expires before the message
00068    exchange terminates, the sender recomputes RT and retransmits the
00069    message.
00070 */
00071 class PANA_RtQueue;
00072 class PANA_RtQueueData
00073 {
00074        friend class PANA_RtQueue;
00075     public:
00076        PANA_RtQueueData() : m_Timeout(0),
00077                             m_Duration(0),
00078                             m_Count(0) { }
00079        virtual ~PANA_RtQueueData() { }
00080        int Timeout() { return m_Timeout; }
00081        virtual PANA_RtQueueData *clone() = 0;
00082        virtual PANA_RtQueueData &operator=(PANA_RtQueueData &d) {
00083            m_Timeout = d.m_Timeout;
00084            m_Duration = d.m_Duration;
00085            m_Count = d.m_Count;
00086            return *this;
00087        }
00088     
00089     protected:
00090        unsigned int m_Timeout;
00091        unsigned int m_Duration;
00092        unsigned int m_Count;
00093 };
00094 
00095 class PANA_RtQueueNullData : public PANA_RtQueueData
00096 {
00097     public:
00098        PANA_RtQueueData *clone() {
00099            return (new PANA_RtQueueNullData(*this));
00100        }
00101 };
00102 
00103 class PANA_RtQueueMsgBlockData : public PANA_RtQueueData
00104 {
00105     public:
00106        PANA_RtQueueMsgBlockData(AAAMessageBlock *blk) :
00107            m_MsgBlock(NULL) {
00108            if (blk) {
00109                m_MsgBlock = AAAMessageBlock::Acquire(ACE_UINT32(blk->size()));
00110                m_MsgBlock->copy(blk->base(), blk->size());
00111            }
00112        }
00113        virtual ~PANA_RtQueueMsgBlockData() {
00114            if (m_MsgBlock) {
00115                m_MsgBlock->Release();
00116            }
00117        }
00118        AAAMessageBlock *MsgBlock() { return m_MsgBlock; }
00119        PANA_RtQueueData *clone() {
00120            PANA_RtQueueData *c = new PANA_RtQueueMsgBlockData(m_MsgBlock);
00121            *c = *this;
00122            // *c(*this);
00123            return (c);
00124        }
00125     protected:
00126        AAAMessageBlock *m_MsgBlock;
00127 };
00128 
00129 class PANA_RtQueueMsgBlockDataWithRcode : public PANA_RtQueueMsgBlockData
00130 {
00131     public:
00132        PANA_RtQueueMsgBlockDataWithRcode(AAAMessageBlock *blk,
00133                                          ACE_UINT32 rCode) :
00134            PANA_RtQueueMsgBlockData(blk), m_Rcode(rCode) { }
00135        virtual ~PANA_RtQueueMsgBlockDataWithRcode() { }
00136        ACE_UINT32 RCode() { return m_Rcode; }
00137        PANA_RtQueueData *clone() {
00138            PANA_RtQueueData *c = new PANA_RtQueueMsgBlockDataWithRcode
00139                                       (m_MsgBlock, m_Rcode);
00140            *c = *this;
00141            return (c);
00142        }
00143     protected:
00144        ACE_UINT32 m_Rcode;
00145 };
00146 
00147 typedef std::list<PANA_RtQueueData*> PANA_RtQueueDataList;
00148 
00149 class PANA_RtQueue : public PANA_RtQueueDataList
00150 {
00151     public:
00152        PANA_RtQueue(int Qsize = 1) : m_MaxQueueCount(Qsize) { }
00153        bool Schedule(PANA_RtQueueData &d) {
00154            if (size() >= m_MaxQueueCount) {
00155                return (false);
00156            }
00157            /*
00158               RT for the first message transmission is based on IRT:
00159               
00160                  RT = IRT + RAND*IRT
00161            */
00162            unsigned int newRt = PANA_CONFIG_GENERAL().rt_.irt_ +
00163                     int(RAND()*float(PANA_CONFIG_GENERAL().rt_.irt_));
00164            
00165            /*
00166               MRT specifies an upper bound on the value of RT
00167               (disregarding the randomization added by the use
00168               of RAND).  If MRT has a value of 0, there is no
00169               upper limit on the value of RT. Otherwise:
00170 
00171                 if (RT > MRT)
00172                     RT = MRT + RAND*MRT
00173            */
00174            if (newRt > PANA_CONFIG_GENERAL().rt_.mrt_) {
00175                newRt = PANA_CONFIG_GENERAL().rt_.mrt_ + 
00176                     int(RAND()*float(PANA_CONFIG_GENERAL().rt_.mrt_));
00177                return false;
00178            }
00179            
00180            d.m_Timeout = newRt;
00181            d.m_Duration = newRt;
00182            d.m_Count = 1;
00183            push_back(d.clone());
00184            return (true);
00185        }
00186        bool ReSchedule(PANA_RtQueueData *&d) {
00187            if (empty()) {
00188                return (false);
00189            }
00190            
00191            PANA_RtQueueData *data = front();
00192            pop_front();
00193 
00194            /*
00195               RT for each subsequent message transmission is
00196               based on the previous value of RT:
00197 
00198                   RT = 2*RTprev + RAND*RTprev
00199            */
00200            unsigned int newRt = 2*data->m_Timeout + 
00201                int(RAND()*float(data->m_Timeout));
00202 
00203            /*
00204               MRT specifies an upper bound on the value of RT
00205               (disregarding the randomization added by the use
00206               of RAND).  If MRT has a value of 0, there is no
00207               upper limit on the value of RT. Otherwise:
00208 
00209                 if (RT > MRT)
00210                     RT = MRT + RAND*MRT
00211            */
00212            if (newRt > PANA_CONFIG_GENERAL().rt_.mrt_) {
00213                newRt = PANA_CONFIG_GENERAL().rt_.mrt_ + 
00214                     int(RAND()*float(PANA_CONFIG_GENERAL().rt_.mrt_));
00215            }
00216            
00217            /*
00218               MRC specifies an upper bound on the number of
00219               times a sender may retransmit a message.  Unless
00220               MRC is zero, the message exchange fails once the
00221               sender has transmitted the message MRC times.
00222 
00223               MRD specifies an upper bound on the length of time
00224               a sender may retransmit a message.  Unless MRD is
00225               zero, the message exchange fails once MRD seconds
00226               have elapsed since the client first transmitted the
00227               message.
00228 
00229               If both MRC and MRD are non-zero, the message exchange
00230               fails whenever either of the conditions specified in
00231               the previous two paragraphs are met.
00232 
00233               If both MRC and MRD are zero, the client continues
00234               to transmit the message until it receives a response.
00235            */
00236            if ((PANA_CONFIG_GENERAL().rt_.mrc_ > 0) &&
00237                (data->m_Count >= PANA_CONFIG_GENERAL().rt_.mrc_)) {
00238                delete data;
00239                return (false);
00240            }
00241            
00242            if ((PANA_CONFIG_GENERAL().rt_.mrd_ > 0) &&
00243                ((data->m_Duration + newRt) > PANA_CONFIG_GENERAL().rt_.mrd_)) {
00244                delete data;
00245                return (false);
00246            }
00247            
00248            data->m_Timeout = newRt;
00249            data->m_Duration += newRt;
00250            data->m_Count ++;
00251            push_back(data);
00252            d = data;
00253            return (true);
00254        }
00255        void ClearFront() {
00256            if (! empty()) {
00257                PANA_RtQueueData *data = front();
00258                pop_front();
00259                delete data;
00260            }
00261        }
00262        void Clear() {
00263            while (! empty()) {
00264                ClearFront();
00265            }
00266        }
00267 
00268     private:
00269        inline float RAND() {
00270            /*
00271               Each of the computations of a new RT include a
00272               randomization factor (RAND), which is a random
00273               number chosen with a uniform distribution between
00274               -0.1 and +0.1.  The randomization factor is included
00275               to minimize synchronization of messages.
00276 
00277               The algorithm for choosing a random number does
00278               not need to be cryptographically sound.  The
00279               algorithm SHOULD produce a different sequence of
00280               random numbers from each invocation.
00281            */
00282            return float(-0.1 + 0.2*float(ACE_OS::rand()/(RAND_MAX+1.0)));
00283        }
00284     
00285        unsigned int m_MaxQueueCount; 
00286 };
00287 
00288 #endif // __PANA_RETRANSMISSION_H__

Generated on Fri Jun 25 19:18:30 2004 for PANA by doxygen 1.3.5