reSIProcate/repro  9694
Classes | Public Types | Public Member Functions | Private Types | Private Member Functions | Private Attributes
repro::RouteStore Class Reference

#include <RouteStore.hxx>

Collaboration diagram for repro::RouteStore:
Collaboration graph
[legend]

List of all members.

Classes

class  RouteOp

Public Types

typedef std::vector< resip::UriUriList
typedef resip::Data Key

Public Member Functions

 RouteStore (AbstractDb &db)
 ~RouteStore ()
bool addRoute (const resip::Data &method, const resip::Data &event, const resip::Data &matchingPattern, const resip::Data &rewriteExpression, const int order)
void eraseRoute (const resip::Data &method, const resip::Data &event, const resip::Data &matchingPattern)
void eraseRoute (const resip::Data &key)
bool updateRoute (const resip::Data &originalKey, const resip::Data &method, const resip::Data &event, const resip::Data &matchingPattern, const resip::Data &rewriteExpression, const int order)
AbstractDb::RouteRecord getRouteRecord (const resip::Data &key)
Key getFirstKey ()
Key getNextKey (Key &key)
UriList process (const resip::Uri &ruri, const resip::Data &method, const resip::Data &event)

Private Types

typedef std::multiset< RouteOpRouteOpList

Private Member Functions

bool findKey (const Key &key)
Key buildKey (const resip::Data &method, const resip::Data &event, const resip::Data &matchingPattern) const

Private Attributes

AbstractDbmDb
resip::RWMutex mMutex
RouteOpList mRouteOperators
RouteOpList::iterator mCursor

Detailed Description

Definition at line 23 of file RouteStore.hxx.


Member Typedef Documentation

Definition at line 27 of file RouteStore.hxx.

typedef std::multiset<RouteOp> repro::RouteStore::RouteOpList [private]

Definition at line 78 of file RouteStore.hxx.

typedef std::vector<resip::Uri> repro::RouteStore::UriList

Definition at line 26 of file RouteStore.hxx.


Constructor & Destructor Documentation

RouteStore::RouteStore ( AbstractDb db)

Definition at line 24 of file RouteStore.cxx.

                                    :
   mDb(db)
{  
   Key key = mDb.firstRouteKey();
   while ( !key.empty() )
   {
      RouteOp route;
      route.routeRecord =  mDb.getRoute(key);
      route.key = key;
      route.preq = 0;
      
      if(!route.routeRecord.mMatchingPattern.empty())
      {
         int flags = REG_EXTENDED;
         if(route.routeRecord.mRewriteExpression.find("$") == Data::npos)
         {
            flags |= REG_NOSUB;
         }
         route.preq = new regex_t;
         int ret = regcomp(route.preq, route.routeRecord.mMatchingPattern.c_str(), flags);
         if(ret != 0)
         {
            delete route.preq;
            ErrLog(<< "Routing rule has invalid match expression: "
                   << route.routeRecord.mMatchingPattern);
            route.preq = 0;
         }
      }

      mRouteOperators.insert( route );

      key = mDb.nextRouteKey();
   } 
   mCursor = mRouteOperators.begin();
}
RouteStore::~RouteStore ( )

Definition at line 61 of file RouteStore.cxx.

{
   for(RouteOpList::iterator i = mRouteOperators.begin(); i != mRouteOperators.end(); i++)
   {
      if ( i->preq )
      {
         regfree ( i->preq );
         delete i->preq;

         // !abr! Can't modify elements in a set
         // i->preq = 0;

      }
   }
   mRouteOperators.clear();
}

Member Function Documentation

bool RouteStore::addRoute ( const resip::Data method,
const resip::Data event,
const resip::Data matchingPattern,
const resip::Data rewriteExpression,
const int  order 
)

Definition at line 80 of file RouteStore.cxx.

{ 
   InfoLog( << "Add route" );
   
   RouteOp route;

   Key key = buildKey(method, event, matchingPattern);
   
   if(findKey(key)) return false;

   route.routeRecord.mMethod = method;
   route.routeRecord.mEvent = event;
   route.routeRecord.mMatchingPattern = matchingPattern;
   route.routeRecord.mRewriteExpression =  rewriteExpression;
   route.routeRecord.mOrder = order;

   if(!mDb.addRoute(key , route.routeRecord))
   {
      return false;
   }

   route.key = key;
   route.preq = 0;
   if( !route.routeRecord.mMatchingPattern.empty() )
   {
     int flags = REG_EXTENDED;
     if( route.routeRecord.mRewriteExpression.find("$") == Data::npos )
     {
       flags |= REG_NOSUB;
     }
     route.preq = new regex_t;
     int ret = regcomp( route.preq, route.routeRecord.mMatchingPattern.c_str(), flags );
     if( ret != 0 )
     {
       delete route.preq;
       route.preq = 0;
     }
   }

   {
      WriteLock lock(mMutex);
      mRouteOperators.insert( route );
   }
   mCursor = mRouteOperators.begin(); 

   return true;
}
RouteStore::Key RouteStore::buildKey ( const resip::Data method,
const resip::Data event,
const resip::Data matchingPattern 
) const [private]

Definition at line 413 of file RouteStore.cxx.

{  
   // missing mOrder
   // Data pKey = Data(order) + ":" + method + ":" + event + ":" + matchingPattern;
   Data pKey = method+":"+event+":"+matchingPattern; 
   return pKey;
}
void RouteStore::eraseRoute ( const resip::Data method,
const resip::Data event,
const resip::Data matchingPattern 
)

Definition at line 151 of file RouteStore.cxx.

{
   Key key = buildKey(method, event, matchingPattern);
   eraseRoute(key);
}
void RouteStore::eraseRoute ( const resip::Data key)

Definition at line 161 of file RouteStore.cxx.

{  
   mDb.eraseRoute(key);

   {
      WriteLock lock(mMutex);

      RouteOpList::iterator it = mRouteOperators.begin();
      while ( it != mRouteOperators.end() )
      {
         if (it->key == key )
         {
            RouteOpList::iterator i = it;
            it++;
            if ( i->preq )
            {
               regfree ( i->preq );
               delete i->preq;

               // !abr! Can't modify elements in a set
               //i->preq = 0;

            }
            mRouteOperators.erase(i);
         }
         else
         {
            it++;
         }
      }
   }
   mCursor = mRouteOperators.begin();  // reset the cursor since it may have been on deleted route
}
bool RouteStore::findKey ( const Key key) [private]

Definition at line 224 of file RouteStore.cxx.

{ 
   // check if cursor happens to be at the key
   if ( mCursor != mRouteOperators.end() )
   {
      if ( mCursor->key == key )
      {
         return true;
      }
   }
   
   // search for the key 
   mCursor = mRouteOperators.begin();
   while (  mCursor != mRouteOperators.end() )
   {
      if ( mCursor->key == key )
      {
         return true; // found the key 
      }
      mCursor++;
   }
   return false; // key was not found 
}
RouteStore::Key RouteStore::getFirstKey ( )

Definition at line 210 of file RouteStore.cxx.

{
   ReadLock lock(mMutex);

   mCursor = mRouteOperators.begin();
   if ( mCursor == mRouteOperators.end() )
   {
      return Key( Data::Empty );
   }
   
   return mCursor->key;
}
RouteStore::Key RouteStore::getNextKey ( Key key)

Definition at line 249 of file RouteStore.cxx.

{  
   ReadLock lock(mMutex);

   if ( !findKey(key) )
   {
      return Key(Data::Empty);
   }
      
   mCursor++;
   
   if ( mCursor == mRouteOperators.end() )
   {
      return Key( Data::Empty );
   }
   
   return mCursor->key;
}
AbstractDb::RouteRecord RouteStore::getRouteRecord ( const resip::Data key)

Definition at line 270 of file RouteStore.cxx.

{
   ReadLock lock(mMutex);

   if (!findKey(key))
   {
      return AbstractDb::RouteRecord();
   }
   return mCursor->routeRecord;
}
RouteStore::UriList RouteStore::process ( const resip::Uri ruri,
const resip::Data method,
const resip::Data event 
)

Definition at line 283 of file RouteStore.cxx.

{
   RouteStore::UriList targetSet;
   if(mRouteOperators.empty()) return targetSet;  // If there are no routes bail early to save a few cycles (size check is atomic enough, we don't need a lock)

   ReadLock lock(mMutex);

   for (RouteOpList::iterator it = mRouteOperators.begin();
        it != mRouteOperators.end(); it++)
   {
      DebugLog( << "Consider route " // << *it
                << " reqUri=" << ruri
                << " method=" << method 
                << " event=" << event );

      const AbstractDb::RouteRecord& rec = it->routeRecord;
      
      if(!rec.mMethod.empty())
      {
         if(!isEqualNoCase(rec.mMethod,method))
         {
            DebugLog( << "  Skipped - method did not match" );
            continue;
         }
         
      }
      if(!rec.mEvent.empty())
      {
         if(!isEqualNoCase(rec.mEvent, event))
         {
            DebugLog( << "  Skipped - event did not match" );
            continue;
         }
      }
      const Data& rewrite = rec.mRewriteExpression;
      const Data& match = rec.mMatchingPattern;
      if ( it->preq ) 
      {
         int ret;
         // TODO - !cj! www.pcre.org looks like it has better performance
         // !mbg! is this true now that the compiled regexp is used?
         Data uri;
         {
            DataStream s(uri);
            s << ruri;
            s.flush();
         }
         
         const int nmatch=10;
         regmatch_t pmatch[nmatch];
         
         ret = regexec(it->preq, uri.c_str(), nmatch, pmatch, 0/*eflags*/);
         if ( ret != 0 )
         {
            // did not match 
            DebugLog( << "  Skipped - request URI "<< uri << " did not match " << match );
            continue;
         }

         DebugLog( << "  Route matched" );
         Data target = rewrite;
         
         if ( rewrite.find("$") != Data::npos )
         {
            for ( int i=1; i<nmatch; i++)
            {
               if ( pmatch[i].rm_so != -1 )
               {
                  Data subExp(uri.substr(pmatch[i].rm_so,
                                         pmatch[i].rm_eo-pmatch[i].rm_so));
                  DebugLog( << "  subExpression[" <<i <<"]="<< subExp );

                  Data result;
                  {
                     DataStream s(result);

                     ParseBuffer pb(target);
                     
                     while (true)
                     {
                        const char* a = pb.position();
                        pb.skipToChars( Data("$") + char('0'+i) );
                        if ( pb.eof() )
                        {
                           s << pb.data(a);
                           break;
                        }
                        else
                        {
                           s << pb.data(a);
                           pb.skipN(2);
                           s <<  subExp;
                        }
                     }
                     s.flush();
                  }
                  target = result;
               }
            }
         }
         
         Uri targetUri;
         try
         {
            targetUri = Uri(target);
         }
         catch( BaseException& )
         {
            ErrLog( << "Routing rule transform " << rewrite << " gave invalid URI " << target );
            try
            {
               targetUri = Uri( Data("sip:")+target);
            }
            catch( BaseException& )
            {
               ErrLog( << "Routing rule transform " << rewrite << " gave invalid URI sip:" << target );
               continue;
            }
         }
         targetSet.push_back( targetUri );
      }
   }

   return targetSet;
}
bool RouteStore::updateRoute ( const resip::Data originalKey,
const resip::Data method,
const resip::Data event,
const resip::Data matchingPattern,
const resip::Data rewriteExpression,
const int  order 
)

Definition at line 197 of file RouteStore.cxx.

{
   eraseRoute(originalKey);
   return addRoute(method, event, matchingPattern, rewriteExpression, order);
}

Member Data Documentation

RouteOpList::iterator repro::RouteStore::mCursor [private]

Definition at line 80 of file RouteStore.hxx.

Definition at line 66 of file RouteStore.hxx.

Definition at line 77 of file RouteStore.hxx.

Definition at line 79 of file RouteStore.hxx.


The documentation for this class was generated from the following files: