|
reSIProcate/repro
9694
|
00001 00002 #include "rutil/Logger.hxx" 00003 #include "rutil/ParseBuffer.hxx" 00004 #include "rutil/Lock.hxx" 00005 #include "resip/stack/Uri.hxx" 00006 00007 #include "repro/RouteStore.hxx" 00008 #include "rutil/WinLeakCheck.hxx" 00009 00010 00011 using namespace resip; 00012 using namespace repro; 00013 using namespace std; 00014 00015 00016 #define RESIPROCATE_SUBSYSTEM Subsystem::REPRO 00017 00018 bool RouteStore::RouteOp::operator<(const RouteOp& rhs) const 00019 { 00020 return routeRecord.mOrder < rhs.routeRecord.mOrder; 00021 } 00022 00023 00024 RouteStore::RouteStore(AbstractDb& db): 00025 mDb(db) 00026 { 00027 Key key = mDb.firstRouteKey(); 00028 while ( !key.empty() ) 00029 { 00030 RouteOp route; 00031 route.routeRecord = mDb.getRoute(key); 00032 route.key = key; 00033 route.preq = 0; 00034 00035 if(!route.routeRecord.mMatchingPattern.empty()) 00036 { 00037 int flags = REG_EXTENDED; 00038 if(route.routeRecord.mRewriteExpression.find("$") == Data::npos) 00039 { 00040 flags |= REG_NOSUB; 00041 } 00042 route.preq = new regex_t; 00043 int ret = regcomp(route.preq, route.routeRecord.mMatchingPattern.c_str(), flags); 00044 if(ret != 0) 00045 { 00046 delete route.preq; 00047 ErrLog(<< "Routing rule has invalid match expression: " 00048 << route.routeRecord.mMatchingPattern); 00049 route.preq = 0; 00050 } 00051 } 00052 00053 mRouteOperators.insert( route ); 00054 00055 key = mDb.nextRouteKey(); 00056 } 00057 mCursor = mRouteOperators.begin(); 00058 } 00059 00060 00061 RouteStore::~RouteStore() 00062 { 00063 for(RouteOpList::iterator i = mRouteOperators.begin(); i != mRouteOperators.end(); i++) 00064 { 00065 if ( i->preq ) 00066 { 00067 regfree ( i->preq ); 00068 delete i->preq; 00069 00070 // !abr! Can't modify elements in a set 00071 // i->preq = 0; 00072 00073 } 00074 } 00075 mRouteOperators.clear(); 00076 } 00077 00078 00079 bool 00080 RouteStore::addRoute(const resip::Data& method, 00081 const resip::Data& event, 00082 const resip::Data& matchingPattern, 00083 const resip::Data& rewriteExpression, 00084 const int order ) 00085 { 00086 InfoLog( << "Add route" ); 00087 00088 RouteOp route; 00089 00090 Key key = buildKey(method, event, matchingPattern); 00091 00092 if(findKey(key)) return false; 00093 00094 route.routeRecord.mMethod = method; 00095 route.routeRecord.mEvent = event; 00096 route.routeRecord.mMatchingPattern = matchingPattern; 00097 route.routeRecord.mRewriteExpression = rewriteExpression; 00098 route.routeRecord.mOrder = order; 00099 00100 if(!mDb.addRoute(key , route.routeRecord)) 00101 { 00102 return false; 00103 } 00104 00105 route.key = key; 00106 route.preq = 0; 00107 if( !route.routeRecord.mMatchingPattern.empty() ) 00108 { 00109 int flags = REG_EXTENDED; 00110 if( route.routeRecord.mRewriteExpression.find("$") == Data::npos ) 00111 { 00112 flags |= REG_NOSUB; 00113 } 00114 route.preq = new regex_t; 00115 int ret = regcomp( route.preq, route.routeRecord.mMatchingPattern.c_str(), flags ); 00116 if( ret != 0 ) 00117 { 00118 delete route.preq; 00119 route.preq = 0; 00120 } 00121 } 00122 00123 { 00124 WriteLock lock(mMutex); 00125 mRouteOperators.insert( route ); 00126 } 00127 mCursor = mRouteOperators.begin(); 00128 00129 return true; 00130 } 00131 00132 00133 /* 00134 AbstractDb::RouteRecordList 00135 RouteStore::getRoutes() const 00136 { 00137 AbstractDb::RouteRecordList result; 00138 result.reserve(mRouteOperators.size()); 00139 00140 for (RouteOpList::const_iterator it = mRouteOperators.begin(); 00141 it != mRouteOperators.end(); it++) 00142 { 00143 result.push_back(it->routeRecord); 00144 } 00145 return result; 00146 } 00147 */ 00148 00149 00150 void 00151 RouteStore::eraseRoute(const resip::Data& method, 00152 const resip::Data& event, 00153 const resip::Data& matchingPattern) 00154 { 00155 Key key = buildKey(method, event, matchingPattern); 00156 eraseRoute(key); 00157 } 00158 00159 00160 void 00161 RouteStore::eraseRoute(const resip::Data& key ) 00162 { 00163 mDb.eraseRoute(key); 00164 00165 { 00166 WriteLock lock(mMutex); 00167 00168 RouteOpList::iterator it = mRouteOperators.begin(); 00169 while ( it != mRouteOperators.end() ) 00170 { 00171 if (it->key == key ) 00172 { 00173 RouteOpList::iterator i = it; 00174 it++; 00175 if ( i->preq ) 00176 { 00177 regfree ( i->preq ); 00178 delete i->preq; 00179 00180 // !abr! Can't modify elements in a set 00181 //i->preq = 0; 00182 00183 } 00184 mRouteOperators.erase(i); 00185 } 00186 else 00187 { 00188 it++; 00189 } 00190 } 00191 } 00192 mCursor = mRouteOperators.begin(); // reset the cursor since it may have been on deleted route 00193 } 00194 00195 00196 bool 00197 RouteStore::updateRoute( const resip::Data& originalKey, 00198 const resip::Data& method, 00199 const resip::Data& event, 00200 const resip::Data& matchingPattern, 00201 const resip::Data& rewriteExpression, 00202 const int order ) 00203 { 00204 eraseRoute(originalKey); 00205 return addRoute(method, event, matchingPattern, rewriteExpression, order); 00206 } 00207 00208 00209 RouteStore::Key 00210 RouteStore::getFirstKey() 00211 { 00212 ReadLock lock(mMutex); 00213 00214 mCursor = mRouteOperators.begin(); 00215 if ( mCursor == mRouteOperators.end() ) 00216 { 00217 return Key( Data::Empty ); 00218 } 00219 00220 return mCursor->key; 00221 } 00222 00223 bool 00224 RouteStore::findKey(const Key& key) 00225 { 00226 // check if cursor happens to be at the key 00227 if ( mCursor != mRouteOperators.end() ) 00228 { 00229 if ( mCursor->key == key ) 00230 { 00231 return true; 00232 } 00233 } 00234 00235 // search for the key 00236 mCursor = mRouteOperators.begin(); 00237 while ( mCursor != mRouteOperators.end() ) 00238 { 00239 if ( mCursor->key == key ) 00240 { 00241 return true; // found the key 00242 } 00243 mCursor++; 00244 } 00245 return false; // key was not found 00246 } 00247 00248 RouteStore::Key 00249 RouteStore::getNextKey(Key& key) 00250 { 00251 ReadLock lock(mMutex); 00252 00253 if ( !findKey(key) ) 00254 { 00255 return Key(Data::Empty); 00256 } 00257 00258 mCursor++; 00259 00260 if ( mCursor == mRouteOperators.end() ) 00261 { 00262 return Key( Data::Empty ); 00263 } 00264 00265 return mCursor->key; 00266 } 00267 00268 00269 AbstractDb::RouteRecord 00270 RouteStore::getRouteRecord(const resip::Data& key) 00271 { 00272 ReadLock lock(mMutex); 00273 00274 if (!findKey(key)) 00275 { 00276 return AbstractDb::RouteRecord(); 00277 } 00278 return mCursor->routeRecord; 00279 } 00280 00281 00282 RouteStore::UriList 00283 RouteStore::process(const resip::Uri& ruri, 00284 const resip::Data& method, 00285 const resip::Data& event ) 00286 { 00287 RouteStore::UriList targetSet; 00288 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) 00289 00290 ReadLock lock(mMutex); 00291 00292 for (RouteOpList::iterator it = mRouteOperators.begin(); 00293 it != mRouteOperators.end(); it++) 00294 { 00295 DebugLog( << "Consider route " // << *it 00296 << " reqUri=" << ruri 00297 << " method=" << method 00298 << " event=" << event ); 00299 00300 const AbstractDb::RouteRecord& rec = it->routeRecord; 00301 00302 if(!rec.mMethod.empty()) 00303 { 00304 if(!isEqualNoCase(rec.mMethod,method)) 00305 { 00306 DebugLog( << " Skipped - method did not match" ); 00307 continue; 00308 } 00309 00310 } 00311 if(!rec.mEvent.empty()) 00312 { 00313 if(!isEqualNoCase(rec.mEvent, event)) 00314 { 00315 DebugLog( << " Skipped - event did not match" ); 00316 continue; 00317 } 00318 } 00319 const Data& rewrite = rec.mRewriteExpression; 00320 const Data& match = rec.mMatchingPattern; 00321 if ( it->preq ) 00322 { 00323 int ret; 00324 // TODO - !cj! www.pcre.org looks like it has better performance 00325 // !mbg! is this true now that the compiled regexp is used? 00326 Data uri; 00327 { 00328 DataStream s(uri); 00329 s << ruri; 00330 s.flush(); 00331 } 00332 00333 const int nmatch=10; 00334 regmatch_t pmatch[nmatch]; 00335 00336 ret = regexec(it->preq, uri.c_str(), nmatch, pmatch, 0/*eflags*/); 00337 if ( ret != 0 ) 00338 { 00339 // did not match 00340 DebugLog( << " Skipped - request URI "<< uri << " did not match " << match ); 00341 continue; 00342 } 00343 00344 DebugLog( << " Route matched" ); 00345 Data target = rewrite; 00346 00347 if ( rewrite.find("$") != Data::npos ) 00348 { 00349 for ( int i=1; i<nmatch; i++) 00350 { 00351 if ( pmatch[i].rm_so != -1 ) 00352 { 00353 Data subExp(uri.substr(pmatch[i].rm_so, 00354 pmatch[i].rm_eo-pmatch[i].rm_so)); 00355 DebugLog( << " subExpression[" <<i <<"]="<< subExp ); 00356 00357 Data result; 00358 { 00359 DataStream s(result); 00360 00361 ParseBuffer pb(target); 00362 00363 while (true) 00364 { 00365 const char* a = pb.position(); 00366 pb.skipToChars( Data("$") + char('0'+i) ); 00367 if ( pb.eof() ) 00368 { 00369 s << pb.data(a); 00370 break; 00371 } 00372 else 00373 { 00374 s << pb.data(a); 00375 pb.skipN(2); 00376 s << subExp; 00377 } 00378 } 00379 s.flush(); 00380 } 00381 target = result; 00382 } 00383 } 00384 } 00385 00386 Uri targetUri; 00387 try 00388 { 00389 targetUri = Uri(target); 00390 } 00391 catch( BaseException& ) 00392 { 00393 ErrLog( << "Routing rule transform " << rewrite << " gave invalid URI " << target ); 00394 try 00395 { 00396 targetUri = Uri( Data("sip:")+target); 00397 } 00398 catch( BaseException& ) 00399 { 00400 ErrLog( << "Routing rule transform " << rewrite << " gave invalid URI sip:" << target ); 00401 continue; 00402 } 00403 } 00404 targetSet.push_back( targetUri ); 00405 } 00406 } 00407 00408 return targetSet; 00409 } 00410 00411 00412 RouteStore::Key 00413 RouteStore::buildKey(const resip::Data& method, 00414 const resip::Data& event, 00415 const resip::Data& matchingPattern ) const 00416 { 00417 // missing mOrder 00418 // Data pKey = Data(order) + ":" + method + ":" + event + ":" + matchingPattern; 00419 Data pKey = method+":"+event+":"+matchingPattern; 00420 return pKey; 00421 } 00422 00423 00424 /* ==================================================================== 00425 * The Vovida Software License, Version 1.0 00426 * 00427 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00428 * 00429 * Redistribution and use in source and binary forms, with or without 00430 * modification, are permitted provided that the following conditions 00431 * are met: 00432 * 00433 * 1. Redistributions of source code must retain the above copyright 00434 * notice, this list of conditions and the following disclaimer. 00435 * 00436 * 2. Redistributions in binary form must reproduce the above copyright 00437 * notice, this list of conditions and the following disclaimer in 00438 * the documentation and/or other materials provided with the 00439 * distribution. 00440 * 00441 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00442 * and "Vovida Open Communication Application Library (VOCAL)" must 00443 * not be used to endorse or promote products derived from this 00444 * software without prior written permission. For written 00445 * permission, please contact vocal@vovida.org. 00446 * 00447 * 4. Products derived from this software may not be called "VOCAL", nor 00448 * may "VOCAL" appear in their name, without prior written 00449 * permission of Vovida Networks, Inc. 00450 * 00451 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00452 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00453 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00454 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00455 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00456 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00457 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00458 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00459 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00460 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00461 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00462 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00463 * DAMAGE. 00464 * 00465 * ==================================================================== 00466 */
1.7.5.1