|
reSIProcate/repro
9694
|
00001 #if defined(HAVE_CONFIG_H) 00002 #include "config.h" 00003 #endif 00004 00005 #include "repro/ProcessorChain.hxx" 00006 #include "repro/Proxy.hxx" 00007 #include "repro/Ack200DoneMessage.hxx" 00008 #include "repro/UserStore.hxx" 00009 #include "repro/Dispatcher.hxx" 00010 00011 #include "resip/stack/TransactionTerminated.hxx" 00012 #include "resip/stack/ApplicationMessage.hxx" 00013 #include "resip/stack/SipStack.hxx" 00014 #include "resip/stack/Helper.hxx" 00015 #include "resip/stack/InteropHelper.hxx" 00016 #include "rutil/Random.hxx" 00017 #include "rutil/Logger.hxx" 00018 #include "rutil/Inserter.hxx" 00019 #include "rutil/WinLeakCheck.hxx" 00020 00021 #define RESIPROCATE_SUBSYSTEM resip::Subsystem::REPRO 00022 00023 using namespace resip; 00024 using namespace repro; 00025 using namespace std; 00026 00027 // Initialize statics 00028 Data Proxy::FlowTokenSalt; 00029 00030 // Use Static fn with static local object to ensure KeyValueStoreKeyAllocator is created before 00031 // static calls to allocate new keys in the monkey classes 00032 KeyValueStore::KeyValueStoreKeyAllocator* Proxy::getGlobalKeyValueStoreKeyAllocator() 00033 { 00034 static KeyValueStore::KeyValueStoreKeyAllocator* globalAllocator = new KeyValueStore::KeyValueStoreKeyAllocator(); 00035 return globalAllocator; 00036 } 00037 00038 KeyValueStore::KeyValueStoreKeyAllocator* Proxy::getRequestKeyValueStoreKeyAllocator() 00039 { 00040 static KeyValueStore::KeyValueStoreKeyAllocator* requestAllocator = new KeyValueStore::KeyValueStoreKeyAllocator(); 00041 return requestAllocator; 00042 } 00043 00044 KeyValueStore::KeyValueStoreKeyAllocator* Proxy::getTargetKeyValueStoreKeyAllocator() 00045 { 00046 static KeyValueStore::KeyValueStoreKeyAllocator* targetAllocator = new KeyValueStore::KeyValueStoreKeyAllocator(); 00047 return targetAllocator; 00048 } 00049 00050 KeyValueStore::Key Proxy::allocateGlobalKeyValueStoreKey() 00051 { 00052 return getGlobalKeyValueStoreKeyAllocator()->allocateNewKey(); 00053 } 00054 00055 KeyValueStore::Key Proxy::allocateRequestKeyValueStoreKey() 00056 { 00057 return getRequestKeyValueStoreKeyAllocator()->allocateNewKey(); 00058 } 00059 00060 KeyValueStore::Key Proxy::allocateTargetKeyValueStoreKey() 00061 { 00062 return getTargetKeyValueStoreKeyAllocator()->allocateNewKey(); 00063 } 00064 00065 RequestContext* 00066 RequestContextFactory::createRequestContext(Proxy& proxy, 00067 ProcessorChain& requestP, // monkeys 00068 ProcessorChain& responseP, // lemurs 00069 ProcessorChain& targetP) // baboons 00070 { 00071 return new RequestContext(proxy, requestP, responseP, targetP); 00072 } 00073 00074 Proxy::Proxy(SipStack& stack, 00075 ProxyConfig& config, 00076 ProcessorChain& requestP, 00077 ProcessorChain& responseP, 00078 ProcessorChain& targetP) 00079 : TransactionUser(TransactionUser::RegisterForTransactionTermination), 00080 mStack(stack), 00081 mConfig(config), 00082 mRecordRoute(config.getConfigUri("RecordRouteUri", Uri())), 00083 mRecordRouteForced(config.getConfigBool("ForceRecordRouting", false)), 00084 mAssumePath(config.getConfigBool("AssumePath", false)), 00085 mPAssertedIdentityProcessing(config.getConfigBool("EnablePAssertedIdentityProcessing", false)), 00086 mServerText(config.getConfigData("ServerText", "")), 00087 mTimerC(config.getConfigInt("TimerC", 180)), 00088 mKeyValueStore(*Proxy::getGlobalKeyValueStoreKeyAllocator()), 00089 mRequestProcessorChain(requestP), 00090 mResponseProcessorChain(responseP), 00091 mTargetProcessorChain(targetP), 00092 mUserStore(config.getDataStore()->mUserStore), 00093 mOptionsHandler(0), 00094 mRequestContextFactory(new RequestContextFactory) 00095 { 00096 FlowTokenSalt = Random::getCryptoRandom(20); // 20-octet Crypto Random Key for Salting Flow Token HMACs 00097 00098 mFifo.setDescription("Proxy::mFifo"); 00099 00100 if(InteropHelper::getOutboundSupported()) 00101 { 00102 addSupportedOption("outbound"); 00103 } 00104 } 00105 00106 00107 Proxy::~Proxy() 00108 { 00109 shutdown(); 00110 join(); 00111 InfoLog (<< "Proxy::thread shutdown with " << mServerRequestContexts.size() << " ServerRequestContexts and " << mClientRequestContexts.size() << " ClientRequestContexts."); 00112 } 00113 00114 void 00115 Proxy::setOptionsHandler(OptionsHandler* handler) 00116 { 00117 mOptionsHandler = handler; 00118 } 00119 00120 void 00121 Proxy::setRequestContextFactory(std::auto_ptr<RequestContextFactory> requestContextFactory) 00122 { 00123 mRequestContextFactory = requestContextFactory; 00124 } 00125 00126 bool 00127 Proxy::isShutDown() const 00128 { 00129 return false; 00130 } 00131 00132 00133 UserStore& 00134 Proxy::getUserStore() 00135 { 00136 return mUserStore; 00137 } 00138 00139 00140 void 00141 Proxy::thread() 00142 { 00143 InfoLog (<< "Proxy::thread start"); 00144 00145 while (!isShutdown()) 00146 { 00147 Message* msg=0; 00148 //DebugLog (<< "TransactionUser::postToTransactionUser " << " &=" << &mFifo << " size=" << mFifo.size()); 00149 00150 try 00151 { 00152 if ((msg = mFifo.getNext(100)) != 0) 00153 { 00154 DebugLog (<< "Got: " << *msg); 00155 00156 SipMessage* sip = dynamic_cast<SipMessage*>(msg); 00157 ApplicationMessage* app = dynamic_cast<ApplicationMessage*>(msg); 00158 TransactionTerminated* term = dynamic_cast<TransactionTerminated*>(msg); 00159 00160 if (sip) 00161 { 00162 Data tid(sip->getTransactionId()); 00163 tid.lowercase(); 00164 if (sip->isRequest()) 00165 { 00166 // Verify that the request has all the mandatory headers 00167 // (To, From, Call-ID, CSeq) Via is already checked by stack. 00168 // See RFC 3261 Section 16.3 Step 1 00169 if (!sip->exists(h_To) || 00170 !sip->exists(h_From) || 00171 !sip->exists(h_CallID) || 00172 !sip->exists(h_CSeq) ) 00173 { 00174 // skip this message and move on to the next one 00175 delete sip; 00176 continue; 00177 } 00178 00179 // The TU selector already checks the URI scheme for us (Sect 16.3, Step 2) 00180 if(sip->method()==OPTIONS && 00181 isMyUri(sip->header(h_RequestLine).uri())) 00182 { 00183 if(mOptionsHandler) 00184 { 00185 std::auto_ptr<SipMessage> resp(new SipMessage); 00186 Helper::makeResponse(*resp,*sip,200); 00187 if(mOptionsHandler->onOptionsRequest(*sip, *resp)) 00188 { 00189 mStack.send(*resp,this); 00190 delete sip; 00191 continue; 00192 } 00193 } 00194 else if(sip->header(h_RequestLine).uri().user().empty()) 00195 { 00196 std::auto_ptr<SipMessage> resp(new SipMessage); 00197 Helper::makeResponse(*resp,*sip,200); 00198 00199 if(resip::InteropHelper::getOutboundSupported()) 00200 { 00201 resp->header(h_Supporteds).push_back(Token("outbound")); 00202 } 00203 mStack.send(*resp,this); 00204 delete sip; 00205 continue; 00206 } 00207 } 00208 00209 // check the MaxForwards isn't too low 00210 if (!sip->exists(h_MaxForwards)) 00211 { 00212 // .bwc. Add Max-Forwards header if not found. 00213 sip->header(h_MaxForwards).value()=20; 00214 } 00215 00216 if(!sip->header(h_MaxForwards).isWellFormed()) 00217 { 00218 //Malformed Max-Forwards! (Maybe we can be lenient and set 00219 // it to 70...) 00220 std::auto_ptr<SipMessage> response(Helper::makeResponse(*sip,400)); 00221 response->header(h_StatusLine).reason()="Malformed Max-Forwards"; 00222 mStack.send(*response,this); 00223 delete sip; 00224 continue; 00225 } 00226 00227 // .bwc. Unacceptable values for Max-Forwards 00228 // !bwc! TODO make this ceiling configurable 00229 if(sip->header(h_MaxForwards).value() > 255) 00230 { 00231 sip->header(h_MaxForwards).value() = 20; 00232 } 00233 else if(sip->header(h_MaxForwards).value() <= 0) 00234 { 00235 if (sip->header(h_RequestLine).method() != OPTIONS) 00236 { 00237 std::auto_ptr<SipMessage> response(Helper::makeResponse(*sip, 483)); 00238 mStack.send(*response, this); 00239 } 00240 else // If the request is an OPTIONS, send an appropriate response 00241 { 00242 std::auto_ptr<SipMessage> response(Helper::makeResponse(*sip, 200)); 00243 mStack.send(*response, this); 00244 } 00245 // in either case get rid of the request and process the next one 00246 delete sip; 00247 continue; 00248 } 00249 00250 if(!sip->empty(h_ProxyRequires)) 00251 { 00252 std::auto_ptr<SipMessage> response(0); 00253 00254 for(Tokens::iterator i=sip->header(h_ProxyRequires).begin(); 00255 i!=sip->header(h_ProxyRequires).end(); 00256 ++i) 00257 { 00258 if(!i->isWellFormed() || 00259 !mSupportedOptions.count(i->value()) ) 00260 { 00261 if(!response.get()) 00262 { 00263 response.reset(Helper::makeResponse(*sip, 420, "Bad extension")); 00264 } 00265 response->header(h_Unsupporteds).push_back(*i); 00266 } 00267 } 00268 00269 if(response.get()) 00270 { 00271 mStack.send(*response, this); 00272 delete sip; 00273 continue; 00274 } 00275 } 00276 00277 00278 if (sip->method() == CANCEL) 00279 { 00280 HashMap<Data,RequestContext*>::iterator i = mServerRequestContexts.find(tid); 00281 00282 if(i == mServerRequestContexts.end()) 00283 { 00284 SipMessage response; 00285 Helper::makeResponse(response,*sip,481); 00286 mStack.send(response,this); 00287 delete sip; 00288 } 00289 else 00290 { 00291 try 00292 { 00293 i->second->process(std::auto_ptr<resip::SipMessage>(sip)); 00294 } 00295 catch(resip::BaseException& e) 00296 { 00297 // .bwc. Some sort of unhandled error in process. 00298 // This is very bad; we cannot form a response 00299 // at this point because we do not know 00300 // whether the original request still exists. 00301 ErrLog(<<"Uncaught exception in process on a CANCEL " 00302 "request: " << e); 00303 mStack.abandonServerTransaction(tid); 00304 } 00305 } 00306 } 00307 else if (sip->method() == ACK) 00308 { 00309 // .bwc. This is going to be treated as a new transaction. 00310 // The stack is maintaining no state whatsoever for this. 00311 // We should treat this exactly like a new transaction. 00312 if(sip->mIsBadAck200) 00313 { 00314 static Data ack("ack"); 00315 tid+=ack; 00316 } 00317 00318 RequestContext* context=0; 00319 00320 HashMap<Data,RequestContext*>::iterator i = mServerRequestContexts.find(tid); 00321 00322 // .bwc. This might be an ACK/200, or a stray ACK/failure 00323 if(i == mServerRequestContexts.end()) 00324 { 00325 context = mRequestContextFactory->createRequestContext(*this, 00326 mRequestProcessorChain, 00327 mResponseProcessorChain, 00328 mTargetProcessorChain); 00329 mServerRequestContexts[tid] = context; 00330 } 00331 else // .bwc. ACK/failure 00332 { 00333 context = i->second; 00334 } 00335 00336 // The stack will send TransactionTerminated messages for 00337 // client and server transaction which will clean up this 00338 // RequestContext 00339 try 00340 { 00341 context->process(std::auto_ptr<resip::SipMessage>(sip)); 00342 } 00343 catch(resip::BaseException& e) 00344 { 00345 // .bwc. Some sort of unhandled error in process. 00346 ErrLog(<<"Uncaught exception in process on an ACK " 00347 "request: " << e); 00348 } 00349 } 00350 else 00351 { 00352 // This is a new request, so create a Request Context for it 00353 InfoLog (<< "New RequestContext tid=" << tid << " : " << sip->brief()); 00354 00355 00356 if(mServerRequestContexts.count(tid) == 0) 00357 { 00358 RequestContext* context = mRequestContextFactory->createRequestContext(*this, 00359 mRequestProcessorChain, 00360 mResponseProcessorChain, 00361 mTargetProcessorChain); 00362 InfoLog (<< "Inserting new RequestContext tid=" << tid 00363 << " -> " << *context); 00364 mServerRequestContexts[tid] = context; 00365 DebugLog (<< "RequestContexts: " << InserterP(mServerRequestContexts)); 00366 try 00367 { 00368 context->process(std::auto_ptr<resip::SipMessage>(sip)); 00369 } 00370 catch(resip::BaseException& e) 00371 { 00372 // .bwc. Some sort of unhandled error in process. 00373 // This is very bad; we cannot form a response 00374 // at this point because we do not know 00375 // whether the original request still exists. 00376 ErrLog(<<"Uncaught exception in process on a new " 00377 "request: " << e); 00378 mStack.abandonServerTransaction(tid); 00379 } 00380 } 00381 else 00382 { 00383 InfoLog(<<"Got a new non-ACK request " 00384 "with an already existing transaction ID. This can " 00385 "happen if a new request collides with a previously " 00386 "received ACK/200."); 00387 SipMessage response; 00388 Helper::makeResponse(response,*sip,400,"Transaction-id " 00389 "collision"); 00390 mStack.send(response,this); 00391 delete sip; 00392 } 00393 } 00394 } 00395 else if (sip->isResponse()) 00396 { 00397 InfoLog (<< "Looking up RequestContext tid=" << tid); 00398 00399 // TODO is there a problem with a stray 200? 00400 HashMap<Data,RequestContext*>::iterator i = mClientRequestContexts.find(tid); 00401 if (i != mClientRequestContexts.end()) 00402 { 00403 try 00404 { 00405 i->second->process(std::auto_ptr<resip::SipMessage>(sip)); 00406 } 00407 catch(resip::BaseException& e) 00408 { 00409 // .bwc. Some sort of unhandled error in process. 00410 ErrLog(<<"Uncaught exception in process on a response: " << e); 00411 } 00412 } 00413 else 00414 { 00415 // throw away stray responses 00416 InfoLog (<< "Unmatched response (stray?) : " << endl << *msg); 00417 delete sip; 00418 } 00419 } 00420 } 00421 else if (app) 00422 { 00423 Data tid(app->getTransactionId()); 00424 tid.lowercase(); 00425 DebugLog(<< "Trying to dispatch : " << *app ); 00426 HashMap<Data,RequestContext*>::iterator i=mServerRequestContexts.find(tid); 00427 // the underlying RequestContext may not exist 00428 if (i != mServerRequestContexts.end()) 00429 { 00430 DebugLog(<< "Sending " << *app << " to " << *(i->second)); 00431 // This goes in as a Message and not an ApplicationMessage 00432 // so that we have one peice of code doing dispatch to Monkeys 00433 // (the intent is that Monkeys may eventually handle non-SIP 00434 // application messages). 00435 bool eraseThisTid = (dynamic_cast<Ack200DoneMessage*>(app)!=0); 00436 try 00437 { 00438 i->second->process(std::auto_ptr<resip::ApplicationMessage>(app)); 00439 } 00440 catch(resip::BaseException& e) 00441 { 00442 ErrLog(<<"Uncaught exception in process: " << e); 00443 } 00444 00445 if (eraseThisTid) 00446 { 00447 mServerRequestContexts.erase(i); 00448 } 00449 } 00450 else 00451 { 00452 InfoLog (<< "No matching request context...ignoring " << *app); 00453 delete app; 00454 } 00455 } 00456 else if (term) 00457 { 00458 Data tid(term->getTransactionId()); 00459 tid.lowercase(); 00460 if (term->isClientTransaction()) 00461 { 00462 HashMap<Data,RequestContext*>::iterator i=mClientRequestContexts.find(tid); 00463 if (i != mClientRequestContexts.end()) 00464 { 00465 try 00466 { 00467 i->second->process(*term); 00468 } 00469 catch(resip::BaseException& e) 00470 { 00471 ErrLog(<<"Uncaught exception in process: " << e); 00472 } 00473 mClientRequestContexts.erase(i); 00474 } 00475 else 00476 { 00477 InfoLog (<< "No matching request context...ignoring " << *term); 00478 } 00479 } 00480 else 00481 { 00482 HashMap<Data,RequestContext*>::iterator i=mServerRequestContexts.find(tid); 00483 if (i != mServerRequestContexts.end()) 00484 { 00485 try 00486 { 00487 i->second->process(*term); 00488 } 00489 catch(resip::BaseException& e) 00490 { 00491 ErrLog(<<"Uncaught exception in process: " << e); 00492 } 00493 mServerRequestContexts.erase(i); 00494 } 00495 else 00496 { 00497 InfoLog (<< "No matching request context...ignoring " << *term); 00498 } 00499 } 00500 delete term; 00501 } 00502 } 00503 } 00504 catch (BaseException& e) 00505 { 00506 ErrLog (<< "Caught: " << e); 00507 } 00508 catch (...) 00509 { 00510 ErrLog (<< "Caught unknown exception"); 00511 } 00512 } 00513 InfoLog (<< "Proxy::thread exit"); 00514 } 00515 00516 void 00517 Proxy::send(const SipMessage& msg) 00518 { 00519 mStack.send(msg, this); 00520 } 00521 00522 void 00523 Proxy::addClientTransaction(const Data& transactionId, RequestContext* rc) 00524 { 00525 if(mClientRequestContexts.count(transactionId) == 0) 00526 { 00527 InfoLog (<< "add client transaction tid=" << transactionId << " " << rc); 00528 mClientRequestContexts[transactionId] = rc; 00529 } 00530 else 00531 { 00532 ErrLog(<< "Received a client request context whose transaction id matches that of an existing request context. Ignoring."); 00533 } 00534 } 00535 00536 void 00537 Proxy::postTimerC(std::auto_ptr<TimerCMessage> tc) 00538 { 00539 if(mTimerC > 0) 00540 { 00541 InfoLog(<<"Posting timer C"); 00542 mStack.post(*tc,mTimerC,this); 00543 } 00544 } 00545 00546 00547 void 00548 Proxy::postMS(std::auto_ptr<resip::ApplicationMessage> msg, int msec) 00549 { 00550 mStack.postMS(*msg,msec,this); 00551 } 00552 00553 00554 const Data& 00555 Proxy::name() const 00556 { 00557 static Data n("Proxy"); 00558 return n; 00559 } 00560 00561 bool 00562 Proxy::isMyUri(const Uri& uri) const 00563 { 00564 bool ret = mStack.isMyDomain(uri.host(), uri.port()); 00565 if(!ret) 00566 { 00567 ret = isMyDomain(uri.host()); 00568 00569 if(ret) 00570 { 00571 // check if we are listening on the specified port 00572 // .slg. this is not perfect, but it will allow us to operate in most environments 00573 // where the repro proxy and a UA are running on the same machine. 00574 // Note: There is a scenario that we cannot correctly handle - when a UA and 00575 // repro are running on the same machine, and they are using the same port but on 00576 // different transports types or interfaces. In this case we cannot tell, by looking 00577 // at a requestUri or From header if the uri is ours or the UA's, and things will break. 00578 if(uri.port() != 0) 00579 { 00580 ret = mStack.isMyPort(uri.port()); 00581 } 00582 } 00583 } 00584 DebugLog( << "Proxy::isMyUri " << uri << " " << ret); 00585 return ret; 00586 } 00587 00588 const resip::NameAddr& 00589 Proxy::getRecordRoute(const Transport* transport) const 00590 { 00591 assert(transport); 00592 if(transport->hasRecordRoute()) 00593 { 00594 // Transport specific record-route found 00595 return transport->getRecordRoute(); 00596 } 00597 return mRecordRoute; 00598 } 00599 00600 bool 00601 Proxy::getRecordRouteForced() const 00602 { 00603 return mRecordRouteForced; 00604 } 00605 00606 bool 00607 Proxy::compressionEnabled() const 00608 { 00609 return mStack.getCompression().getAlgorithm() != resip::Compression::NONE; 00610 } 00611 00612 void 00613 Proxy::addSupportedOption(const resip::Data& option) 00614 { 00615 mSupportedOptions.insert(option); 00616 } 00617 00618 void 00619 Proxy::removeSupportedOption(const resip::Data& option) 00620 { 00621 mSupportedOptions.erase(option); 00622 } 00623 00624 00625 00626 /* ==================================================================== 00627 * The Vovida Software License, Version 1.0 00628 * 00629 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00630 * 00631 * Redistribution and use in source and binary forms, with or without 00632 * modification, are permitted provided that the following conditions 00633 * are met: 00634 * 00635 * 1. Redistributions of source code must retain the above copyright 00636 * notice, this list of conditions and the following disclaimer. 00637 * 00638 * 2. Redistributions in binary form must reproduce the above copyright 00639 * notice, this list of conditions and the following disclaimer in 00640 * the documentation and/or other materials provided with the 00641 * distribution. 00642 * 00643 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00644 * and "Vovida Open Communication Application Library (VOCAL)" must 00645 * not be used to endorse or promote products derived from this 00646 * software without prior written permission. For written 00647 * permission, please contact vocal@vovida.org. 00648 * 00649 * 4. Products derived from this software may not be called "VOCAL", nor 00650 * may "VOCAL" appear in their name, without prior written 00651 * permission of Vovida Networks, Inc. 00652 * 00653 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00654 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00655 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00656 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00657 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00658 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00659 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00660 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00661 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00662 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00663 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00664 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00665 * DAMAGE. 00666 * 00667 * ==================================================================== 00668 */
1.7.5.1