reSIProcate/stack  9694
TuSelector.cxx
Go to the documentation of this file.
00001 #include "resip/stack/ConnectionTerminated.hxx"
00002 #include "resip/stack/KeepAlivePong.hxx"
00003 #include "resip/stack/TuSelector.hxx"
00004 #include "resip/stack/TransactionUser.hxx"
00005 #include "resip/stack/TransactionUserMessage.hxx"
00006 #include "resip/stack/SipStack.hxx"
00007 
00008 #include "rutil/TimeLimitFifo.hxx"
00009 #include "rutil/AsyncProcessHandler.hxx"
00010 #include "rutil/WinLeakCheck.hxx"
00011 #include "rutil/Logger.hxx"
00012 #define RESIPROCATE_SUBSYSTEM Subsystem::TRANSACTION
00013 
00014 using namespace resip;
00015 
00016 TuSelector::TuSelector(TimeLimitFifo<Message>& fallBackFifo) :
00017    mFallBackFifo(fallBackFifo), 
00018    mCongestionManager(0),
00019    mFallbackPostNotify(0),
00020    mTuSelectorMode(false),
00021    mStatsPayload()
00022 {
00023    mShutdownFifo.setDescription("TuSelector::mShutdownFifo");
00024 }
00025 
00026 TuSelector::~TuSelector()
00027 {
00028    //assert(mTuList.empty());
00029 }
00030 
00031 
00032 void
00033 TuSelector::setFallbackPostNotify(AsyncProcessHandler *handler) 
00034 {
00035     mFallbackPostNotify = handler;
00036 }
00037 
00038 void
00039 TuSelector::process()
00040 {
00041    if (mShutdownFifo.messageAvailable())
00042    {
00043       TransactionUserMessage* msg = mShutdownFifo.getNext();
00044       
00045       switch (msg->type())
00046       {
00047          case TransactionUserMessage::RequestShutdown:
00048             InfoLog (<< "TransactionUserMessage::RequestShutdown " << *(msg->getTransactionUser()));
00049             markShuttingDown(msg->getTransactionUser());
00050             break;
00051          case TransactionUserMessage::RemoveTransactionUser:
00052             InfoLog (<< "TransactionUserMessage::RemoveTransactionUser " << *(msg->getTransactionUser()));
00053             remove(msg->getTransactionUser());
00054             break;
00055          default:
00056             assert(0);
00057             break;
00058       }
00059       delete msg;
00060    }
00061 }
00062 
00063 void
00064 TuSelector::add(Message* msg, TimeLimitFifo<Message>::DepthUsage usage)
00065 {
00066    if (msg->hasTransactionUser())
00067    {
00068       if (exists(msg->getTransactionUser()))
00069       {
00070          DebugLog (<< "Send to TU: " << *(msg->getTransactionUser()) << " " << std::endl << std::endl << *msg);
00071          msg->getTransactionUser()->postToTransactionUser(msg, usage);
00072       }
00073       else
00074       {
00075          WarningLog (<< "Send to TU that no longer exists: " << std::endl << std::endl << *msg);
00076          delete msg;
00077       }
00078    }
00079    else
00080    {
00081       StatisticsMessage* stats = dynamic_cast<StatisticsMessage*>(msg);
00082       if (stats)
00083       {
00084          InfoLog(<< "Stats message " );
00085          stats->loadOut(mStatsPayload);
00086          stats->logStats(RESIPROCATE_SUBSYSTEM, mStatsPayload);
00087          delete msg;
00088       }
00089       else
00090       {
00091          DebugLog(<< "Send to default TU: " << std::endl << std::endl << *msg);
00092          mFallBackFifo.add(msg, usage);
00093          if ( mFallbackPostNotify )
00094             mFallbackPostNotify->handleProcessNotification();
00095       }
00096    }
00097 }
00098 
00099 void
00100 TuSelector::add(ConnectionTerminated* term)
00101 {
00102    InfoLog (<< "Sending " << *term << " to TUs");
00103    
00104    for(TuList::const_iterator it = mTuList.begin(); it != mTuList.end(); it++)
00105    {
00106       if (!it->shuttingDown && it->tu->isRegisteredForConnectionTermination())
00107       {
00108          it->tu->post(term->clone());
00109       }
00110    }
00111 }
00112 
00113 void 
00114 TuSelector::add(KeepAlivePong* pong)
00115 {
00116    //InfoLog (<< "Sending " << *pong << " to TUs");
00117    
00118    for(TuList::const_iterator it = mTuList.begin(); it != mTuList.end(); it++)
00119    {
00120       if (!it->shuttingDown && it->tu->isRegisteredForKeepAlivePongs())
00121       {
00122          it->tu->post(pong->clone());
00123       }
00124    }
00125 }
00126 
00127 bool
00128 TuSelector::wouldAccept(TimeLimitFifo<Message>::DepthUsage usage) const
00129 {
00130    if (mTuSelectorMode)
00131    {
00132       for(TuList::const_iterator it = mTuList.begin(); it != mTuList.end(); it++)
00133       {
00134          if (!it->shuttingDown  && !it->tu->wouldAccept(usage))
00135          {
00136             return false;
00137          }
00138       }
00139       return true;
00140    }
00141    else
00142    {
00143       return mFallBackFifo.wouldAccept(usage);
00144    }
00145 }
00146       
00147 unsigned int 
00148 TuSelector::size() const      
00149 {
00150    if (mTuSelectorMode)
00151    {
00152       unsigned int total=0;   
00153       for(TuList::const_iterator it = mTuList.begin(); it != mTuList.end(); it++)
00154       {
00155          total += it->tu->size();
00156       }
00157       return total;
00158    }
00159    else
00160    {
00161       return mFallBackFifo.size();
00162    }
00163 }
00164 
00165 void 
00166 TuSelector::registerTransactionUser(TransactionUser& tu)
00167 {
00168    mTuSelectorMode = true;
00169    mTuList.push_back(Item(&tu));
00170 }
00171 
00172 void
00173 TuSelector::requestTransactionUserShutdown(TransactionUser& tu)
00174 {
00175    TransactionUserMessage* msg = new TransactionUserMessage(TransactionUserMessage::RequestShutdown, &tu);
00176    mShutdownFifo.add(msg);
00177 }
00178 
00179 void
00180 TuSelector::unregisterTransactionUser(TransactionUser& tu)
00181 {
00182    TransactionUserMessage* msg = new TransactionUserMessage(TransactionUserMessage::RemoveTransactionUser, &tu);
00183    mShutdownFifo.add(msg);
00184 }
00185 
00186 TransactionUser* 
00187 TuSelector::selectTransactionUser(const SipMessage& msg)
00188 {
00189    for(TuList::iterator it = mTuList.begin(); it != mTuList.end(); it++)
00190    {
00191       if (it->tu->isForMe(msg))
00192       {
00193          return it->tu;
00194       }
00195    }
00196    return 0;
00197 }
00198 
00199 void
00200 TuSelector::markShuttingDown(TransactionUser* tu)
00201 {
00202    for(TuList::iterator it = mTuList.begin(); it != mTuList.end(); it++)
00203    {
00204       if (it->tu == tu)
00205       {
00206          it->shuttingDown = true;
00207          return;
00208       }
00209    }
00210    assert(0);
00211 }
00212 
00213 void
00214 TuSelector::remove(TransactionUser* tu)
00215 {
00216    for(TuList::iterator it = mTuList.begin(); it != mTuList.end(); it++)
00217    {
00218       if (it->tu == tu)
00219       {
00220          TransactionUserMessage* done = new TransactionUserMessage(TransactionUserMessage::TransactionUserRemoved, tu);
00221          tu->post(done);
00222          mTuList.erase(it);
00223          return;
00224       }
00225    }
00226    assert(0);
00227 }
00228 
00229 bool
00230 TuSelector::exists(TransactionUser* tu)
00231 {
00232    for(TuList::iterator it = mTuList.begin(); it != mTuList.end(); it++)
00233    {
00234       if (it->tu == tu)
00235       {
00236          return true;
00237       }
00238    }
00239    return false;
00240 }
00241 
00242 unsigned int 
00243 TuSelector::getTimeTillNextProcessMS()
00244 {
00245     if(mShutdownFifo.messageAvailable()) //  || !mFallBackFifo.messageAvailable())  // .slg. fallback fifo is not really used
00246     {
00247         return 0;
00248     }
00249     else
00250     {
00251         return INT_MAX;
00252     }
00253 } 
00254 
00255 bool
00256 TuSelector::isTransactionUserStillRegistered(const TransactionUser* tu) const
00257 {
00258    if (mTuSelectorMode)
00259    {
00260       for(TuList::const_iterator it = mTuList.begin(); it != mTuList.end(); it++)
00261       {
00262          if (!it->shuttingDown  && it->tu == tu)
00263          {
00264             return true;
00265          }
00266       }
00267    }
00268    return false;
00269 }
00270 
00271 void 
00272 TuSelector::setCongestionManager(CongestionManager* manager)
00273 {
00274    for(TuList::iterator i=mTuList.begin(); i!=mTuList.end();++i)
00275    {
00276       i->tu->setCongestionManager(manager);
00277    }
00278    
00279    // Note:  We are intentionally not registering the following Fifos
00280    // mFallbackFifo - this is the same fifo as SipStack::TuFifo (passed in 
00281    //                 constructor).
00282    // mShutdownFifo - since it is only used at shutdown time, it doesn need
00283    //                 congestion management
00284 }
00285 
00286 CongestionManager::RejectionBehavior 
00287 TuSelector::getRejectionBehavior(TransactionUser* tu) const
00288 {
00289    if(!mCongestionManager)
00290    {
00291       return CongestionManager::NORMAL;
00292    }
00293 
00294    if(tu)
00295    {
00296       return tu->getRejectionBehavior();
00297    }
00298 
00299    return mCongestionManager->getRejectionBehavior(&mFallBackFifo);
00300 }
00301 
00302 UInt32 
00303 TuSelector::getExpectedWait(TransactionUser* tu) const
00304 {
00305    if(tu)
00306    {
00307       return tu->getExpectedWait();
00308    }
00309 
00310    return (UInt32)mFallBackFifo.expectedWaitTimeMilliSec();
00311 }
00312 
00313 
00314 
00315 /* ====================================================================
00316  * The Vovida Software License, Version 1.0 
00317  * 
00318  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00319  * 
00320  * Redistribution and use in source and binary forms, with or without
00321  * modification, are permitted provided that the following conditions
00322  * are met:
00323  * 
00324  * 1. Redistributions of source code must retain the above copyright
00325  *    notice, this list of conditions and the following disclaimer.
00326  * 
00327  * 2. Redistributions in binary form must reproduce the above copyright
00328  *    notice, this list of conditions and the following disclaimer in
00329  *    the documentation and/or other materials provided with the
00330  *    distribution.
00331  * 
00332  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00333  *    and "Vovida Open Communication Application Library (VOCAL)" must
00334  *    not be used to endorse or promote products derived from this
00335  *    software without prior written permission. For written
00336  *    permission, please contact vocal@vovida.org.
00337  *
00338  * 4. Products derived from this software may not be called "VOCAL", nor
00339  *    may "VOCAL" appear in their name, without prior written
00340  *    permission of Vovida Networks, Inc.
00341  * 
00342  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00343  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00344  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00345  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00346  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00347  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00348  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00349  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00350  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00351  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00352  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00353  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00354  * DAMAGE.
00355  * 
00356  * ====================================================================
00357  * 
00358  * This software consists of voluntary contributions made by Vovida
00359  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00360  * Inc.  For more information on Vovida Networks, Inc., please see
00361  * <http://www.vovida.org/>.
00362  *
00363  */