1
#if defined(HAVE_CONFIG_H)
9
#include "rutil/Log.hxx"
10
#include "rutil/Logger.hxx"
11
#include "rutil/DnsUtil.hxx"
12
#include "rutil/dns/DnsStub.hxx"
13
#include "rutil/GeneralCongestionManager.hxx"
15
#include "resip/stack/SipStack.hxx"
16
#include "resip/stack/Compression.hxx"
17
#include "resip/stack/EventStackThread.hxx"
18
#include "resip/stack/InteropHelper.hxx"
19
#include "resip/stack/ConnectionManager.hxx"
21
#include "resip/dum/InMemorySyncRegDb.hxx"
22
#include "resip/dum/MasterProfile.hxx"
23
#include "resip/dum/DialogUsageManager.hxx"
24
#include "resip/dum/DumThread.hxx"
25
#include "resip/dum/TlsPeerAuthManager.hxx"
27
#include "repro/AsyncProcessorWorker.hxx"
28
#include "repro/ReproRunner.hxx"
29
#include "repro/Proxy.hxx"
30
#include "repro/ProxyConfig.hxx"
31
#include "repro/BerkeleyDb.hxx"
32
#include "repro/Dispatcher.hxx"
33
#include "repro/UserAuthGrabber.hxx"
34
#include "repro/ProcessorChain.hxx"
35
#include "repro/ReproVersion.hxx"
36
#include "repro/WebAdmin.hxx"
37
#include "repro/WebAdminThread.hxx"
38
#include "repro/Registrar.hxx"
39
#include "repro/ReproServerAuthManager.hxx"
40
#include "repro/RegSyncClient.hxx"
41
#include "repro/RegSyncServer.hxx"
42
#include "repro/RegSyncServerThread.hxx"
43
#include "repro/CommandServer.hxx"
44
#include "repro/CommandServerThread.hxx"
45
#include "repro/monkeys/IsTrustedNode.hxx"
46
#include "repro/monkeys/AmIResponsible.hxx"
47
#include "repro/monkeys/DigestAuthenticator.hxx"
48
#include "repro/monkeys/LocationServer.hxx"
49
#include "repro/monkeys/RecursiveRedirect.hxx"
50
#include "repro/monkeys/SimpleStaticRoute.hxx"
51
#include "repro/monkeys/StaticRoute.hxx"
52
#include "repro/monkeys/StrictRouteFixup.hxx"
53
#include "repro/monkeys/OutboundTargetHandler.hxx"
54
#include "repro/monkeys/QValueTargetHandler.hxx"
55
#include "repro/monkeys/SimpleTargetHandler.hxx"
56
#include "repro/monkeys/GeoProximityTargetSorter.hxx"
57
#include "repro/monkeys/RequestFilter.hxx"
58
#include "repro/monkeys/MessageSilo.hxx"
59
#include "repro/monkeys/CertificateAuthenticator.hxx"
62
#include "repro/stateAgents/CertServer.hxx"
63
#include "resip/stack/ssl/Security.hxx"
66
#if defined(USE_MYSQL)
67
#include "repro/MySqlDb.hxx"
70
#include "rutil/WinLeakCheck.hxx"
72
#define RESIPROCATE_SUBSYSTEM resip::Subsystem::REPRO
74
using namespace resip;
75
using namespace repro;
78
class ReproLogger : public ExternalLogger
81
virtual ~ReproLogger() {}
82
/** return true to also do default logging, false to supress default logging. */
83
virtual bool operator()(Log::Level level,
84
const Subsystem& subsystem,
89
const Data& messageWithHeaders)
91
// Log any errors to the screen
94
resipCout << messageWithHeaders << endl;
99
ReproLogger g_ReproLogger;
101
ReproRunner::ReproRunner()
104
, mThreadedStack(false)
105
, mSipAuthDisabled(false)
111
, mAsyncProcessHandler(0)
115
, mRuntimeAbstractDb(0)
116
, mRegistrationPersistenceManager(0)
117
, mAuthRequestDispatcher(0)
118
, mAsyncProcessorDispatcher(0)
130
, mRegSyncServerV4(0)
131
, mRegSyncServerV6(0)
132
, mRegSyncServerThread(0)
133
, mCommandServerV4(0)
134
, mCommandServerV6(0)
135
, mCommandServerThread(0)
136
, mCongestionManager(0)
140
ReproRunner::~ReproRunner()
142
if(mRunning) shutdown();
146
ReproRunner::run(int argc, char** argv)
148
if(mRunning) return false;
152
// Store original arc and argv - so we can reuse them on restart request
157
// Parse command line and configuration file
158
assert(!mProxyConfig);
159
Data defaultConfigFilename("repro.config");
162
mProxyConfig = new ProxyConfig();
163
mProxyConfig->parseConfig(mArgc, mArgv, defaultConfigFilename);
165
catch(BaseException& ex)
167
std::cerr << "Error parsing configuration: " << ex << std::endl;
171
// Non-Windows server process stuff
174
setPidFile(mProxyConfig->getConfigData("PidFile", "", true));
175
if(mProxyConfig->getConfigBool("Daemonize", false))
181
// Initialize resip logger
182
GenericLogImpl::MaxByteCount = mProxyConfig->getConfigUnsignedLong("LogFileMaxBytes", 5242880 /*5 Mb */);
183
Data loggingType = mProxyConfig->getConfigData("LoggingType", "cout", true);
184
Log::initialize(loggingType,
185
mProxyConfig->getConfigData("LogLevel", "INFO", true),
187
mProxyConfig->getConfigData("LogFilename", "repro.log", true).c_str(),
188
isEqualNoCase(loggingType, "file") ? &g_ReproLogger : 0); // if logging to file then write WARNINGS, and Errors to console still
190
InfoLog( << "Starting repro version " << VersionUtils::instance().releaseVersion() << "...");
192
// Create SipStack and associated objects
193
if(!createSipStack())
199
if(!createDatastore())
204
// Create DialogUsageManager that handles ServerRegistration,
205
// and potentially certificate subscription server
206
createDialogUsageManager();
208
// Create the Proxy and associate objects
214
// Create HTTP WebAdmin and Thread
215
if(!createWebAdmin())
220
// Create reg sync components if required
223
// Create command server if required
226
createCommandServer();
229
// Make it all go - startup all threads
230
mThreadedStack = mProxyConfig->getConfigBool("ThreadedStack", true);
233
// If configured, then start the sub-threads within the stack
244
mWebAdminThread->run();
246
if(!mRestarting && mCommandServerThread)
248
mCommandServerThread->run();
250
if(mRegSyncServerThread)
252
mRegSyncServerThread->run();
256
mRegSyncClient->run();
265
ReproRunner::shutdown()
267
if(!mRunning) return;
269
// Tell all threads to shutdown
272
mWebAdminThread->shutdown();
276
mDumThread->shutdown();
279
mStackThread->shutdown();
280
if(!mRestarting && mCommandServerThread) // leave command server running if we are restarting
282
mCommandServerThread->shutdown();
284
if(mRegSyncServerThread)
286
mRegSyncServerThread->shutdown();
290
mRegSyncClient->shutdown();
293
// Wait for all threads to shutdown, and destroy objects
297
mSipStack->shutdownAndJoinThreads();
299
mStackThread->join();
302
mWebAdminThread->join();
308
if(mAuthRequestDispatcher)
310
// Both proxy and dum threads are down at this point, we can
311
// destroy the authRequest dispatcher and associated threads now
312
delete mAuthRequestDispatcher;
313
mAuthRequestDispatcher = 0;
315
if(mAsyncProcessorDispatcher)
317
// Both proxy and dum threads are down at this point, we can
318
// destroy the async processor dispatcher and associated threads now
319
delete mAsyncProcessorDispatcher;
320
mAsyncProcessorDispatcher = 0;
322
if(!mRestarting && mCommandServerThread) // we leave command server running during restart
324
mCommandServerThread->join();
326
if(mRegSyncServerThread)
328
mRegSyncServerThread->join();
332
mRegSyncClient->join();
335
mSipStack->setCongestionManager(0);
342
ReproRunner::restart()
344
if(!mRunning) return;
352
ReproRunner::cleanupObjects()
354
delete mCongestionManager; mCongestionManager = 0;
357
// We leave command server running during restart
358
delete mCommandServerThread; mCommandServerThread = 0;
359
delete mCommandServerV6; mCommandServerV6 = 0;
360
delete mCommandServerV4; mCommandServerV4 = 0;
362
delete mRegSyncServerThread; mRegSyncServerThread = 0;
363
delete mRegSyncServerV6; mRegSyncServerV6 = 0;
364
delete mRegSyncServerV4; mRegSyncServerV4 = 0;
365
delete mRegSyncClient; mRegSyncClient = 0;
367
delete mCertServer; mCertServer = 0;
369
delete mDumThread; mDumThread = 0;
370
delete mDum; mDum = 0;
371
delete mRegistrar; mRegistrar = 0;
372
delete mWebAdminThread; mWebAdminThread = 0;
373
delete mWebAdmin; mWebAdmin = 0;
374
delete mProxy; mProxy = 0;
375
delete mBaboons; mBaboons = 0;
376
delete mLemurs; mLemurs = 0;
377
delete mMonkeys; mMonkeys = 0;
378
delete mAuthRequestDispatcher; mAuthRequestDispatcher = 0;
379
delete mAsyncProcessorDispatcher; mAsyncProcessorDispatcher = 0;
382
// If we are restarting then leave the In Memory Registration database intact
383
delete mRegistrationPersistenceManager; mRegistrationPersistenceManager = 0;
385
delete mAbstractDb; mAbstractDb = 0;
386
delete mRuntimeAbstractDb; mRuntimeAbstractDb = 0;
387
delete mStackThread; mStackThread = 0;
388
delete mSipStack; mSipStack = 0;
389
delete mAsyncProcessHandler; mAsyncProcessHandler = 0;
390
delete mFdPollGrp; mFdPollGrp = 0;
391
delete mProxyConfig; mProxyConfig = 0;
395
ReproRunner::createSipStack()
397
// Override T1 timer if configured to do so
398
unsigned long overrideT1 = mProxyConfig->getConfigInt("TimerT1", 0);
401
WarningLog(<< "Overriding T1! (new value is " <<
403
resip::Timer::resetT1(overrideT1);
406
// Create Security (TLS / Certificates) and Compression (SigComp) objects if
407
// pre-precessor defines are enabled
408
Security* security = 0;
409
Compression* compression = 0;
412
Data certPath("C:\\sipCerts");
414
Data certPath(getenv("HOME"));
415
certPath += "/.sipCerts";
417
mProxyConfig->getConfigValue("CertificatePath", certPath);
418
security = new Security(certPath);
420
mProxyConfig->getConfigValue("CADirectory", caDir);
423
security->addCADirectory(caDir);
426
mProxyConfig->getConfigValue("CAFile", caFile);
429
security->addCAFile(caFile);
434
compression = new Compression(Compression::DEFLATE);
437
// Create EventThreadInterruptor used to wake up the stack for
438
// for reasons other than an Fd signalling
440
mFdPollGrp = FdPollGrp::create();
441
assert(!mAsyncProcessHandler);
442
mAsyncProcessHandler = new EventThreadInterruptor(*mFdPollGrp);
444
// Set Flags that will enable/disable IPv4 and/or IPv6, based on
445
// configuration and pre-processor flags
446
mUseV4 = !mProxyConfig->getConfigBool("DisableIPv4", false);
448
mUseV6 = mProxyConfig->getConfigBool("EnableIPv6", true);
452
if (mUseV4) InfoLog (<< "V4 enabled");
453
if (mUseV6) InfoLog (<< "V6 enabled");
455
// Build DNS Server list from config
456
DnsStub::NameserverList dnsServers;
457
std::vector<resip::Data> dnsServersConfig;
458
mProxyConfig->getConfigValue("DNSServers", dnsServersConfig);
459
for(std::vector<resip::Data>::iterator it = dnsServersConfig.begin(); it != dnsServersConfig.end(); it++)
461
if((mUseV4 && DnsUtil::isIpV4Address(*it)) || (mUseV6 && DnsUtil::isIpV6Address(*it)))
463
InfoLog(<< "Using DNS Server from config: " << *it);
464
dnsServers.push_back(Tuple(*it, 0, UNKNOWN_TRANSPORT).toGenericIPAddress());
468
// Create the SipStack Object
470
mSipStack = new SipStack(security,
472
mAsyncProcessHandler,
478
// Set any enum suffixes from configuration
479
std::vector<Data> enumSuffixes;
480
mProxyConfig->getConfigValue("EnumSuffixes", enumSuffixes);
481
if (enumSuffixes.size() > 0)
483
mSipStack->setEnumSuffixes(enumSuffixes);
486
// Set any enum domains from configuration
487
std::map<Data,Data> enumDomains;
488
std::vector<Data> _enumDomains;
489
mProxyConfig->getConfigValue("EnumDomains", _enumDomains);
490
if (enumSuffixes.size() > 0)
492
for(std::vector<Data>::iterator it = _enumDomains.begin(); it != _enumDomains.end(); it++)
494
enumDomains[*it] = *it;
496
mSipStack->setEnumDomains(enumDomains);
499
// Add stack transports
500
bool allTransportsSpecifyRecordRoute=false;
501
if(!addTransports(allTransportsSpecifyRecordRoute))
507
// Enable and configure RFC5626 Outbound support
508
InteropHelper::setOutboundVersion(mProxyConfig->getConfigInt("OutboundVersion", 5626));
509
InteropHelper::setOutboundSupported(mProxyConfig->getConfigBool("DisableOutbound", false) ? false : true);
510
InteropHelper::setRRTokenHackEnabled(mProxyConfig->getConfigBool("EnableFlowTokens", false));
511
InteropHelper::setAssumeFirstHopSupportsOutboundEnabled(mProxyConfig->getConfigBool("AssumeFirstHopSupportsOutbound", false));
512
Data clientNATDetectionMode = mProxyConfig->getConfigData("ClientNatDetectionMode", "DISABLED");
513
if(isEqualNoCase(clientNATDetectionMode, "ENABLED"))
515
InteropHelper::setClientNATDetectionMode(InteropHelper::ClientNATDetectionEnabled);
517
else if(isEqualNoCase(clientNATDetectionMode, "PRIVATE_TO_PUBLIC"))
519
InteropHelper::setClientNATDetectionMode(InteropHelper::ClientNATDetectionPrivateToPublicOnly);
521
unsigned long outboundFlowTimer = mProxyConfig->getConfigUnsignedLong("FlowTimer", 0);
522
if(outboundFlowTimer > 0)
524
InteropHelper::setFlowTimerSeconds(outboundFlowTimer);
525
ConnectionManager::MinimumGcAge = 7200000; // Timeout connections not related to a flow timer after 2 hours - TODO make configurable
526
ConnectionManager::EnableAgressiveGc = true;
529
// Check Path and RecordRoute settings, print warning if features are enabled that
530
// require record-routing and record-route uri(s) is not configured
531
bool assumePath = mProxyConfig->getConfigBool("AssumePath", false);
532
bool forceRecordRoute = mProxyConfig->getConfigBool("ForceRecordRouting", false);
534
mProxyConfig->getConfigValue("RecordRouteUri", recordRouteUri);
535
if((InteropHelper::getOutboundSupported()
536
|| InteropHelper::getRRTokenHackEnabled()
537
|| InteropHelper::getClientNATDetectionMode() != InteropHelper::ClientNATDetectionDisabled
541
&& !(allTransportsSpecifyRecordRoute || !recordRouteUri.host().empty()))
543
CritLog(<< "In order for outbound support, the Record-Route flow-token"
544
" hack, or force-record-route to work, you MUST specify a Record-Route URI. Launching "
546
InteropHelper::setOutboundSupported(false);
547
InteropHelper::setRRTokenHackEnabled(false);
548
InteropHelper::setClientNATDetectionMode(InteropHelper::ClientNATDetectionDisabled);
550
forceRecordRoute=false;
553
// Configure misc. stack settings
554
mSipStack->setFixBadDialogIdentifiers(false);
555
mSipStack->setFixBadCSeqNumbers(false);
556
int statsLogInterval = mProxyConfig->getConfigInt("StatisticsLogInterval", 60);
557
if(statsLogInterval > 0)
559
mSipStack->setStatisticsInterval(statsLogInterval);
560
mSipStack->statisticsManagerEnabled() = true;
564
mSipStack->statisticsManagerEnabled() = false;
567
// Create Congestion Manager, if required
568
assert(!mCongestionManager);
569
if(mProxyConfig->getConfigBool("CongestionManagement", true))
571
Data metricData = mProxyConfig->getConfigData("CongestionManagementMetric", "WAIT_TIME", true);
572
GeneralCongestionManager::MetricType metric = GeneralCongestionManager::WAIT_TIME;
573
if(isEqualNoCase(metricData, "TIME_DEPTH"))
575
metric = GeneralCongestionManager::TIME_DEPTH;
577
else if(isEqualNoCase(metricData, "SIZE"))
579
metric = GeneralCongestionManager::SIZE;
581
else if(!isEqualNoCase(metricData, "WAIT_TIME"))
583
WarningLog( << "CongestionManagementMetric specified as an unknown value (" << metricData << "), defaulting to WAIT_TIME.");
585
mCongestionManager = new GeneralCongestionManager(
587
mProxyConfig->getConfigUnsignedLong("CongestionManagementTolerance", 200));
588
mSipStack->setCongestionManager(mCongestionManager);
591
// Create base thread to run stack in (note: stack may use other sub-threads, depending on configuration)
592
assert(!mStackThread);
593
mStackThread = new EventStackThread(*mSipStack,
594
*dynamic_cast<EventThreadInterruptor*>(mAsyncProcessHandler),
600
ReproRunner::createDatastore()
602
// Create Database access objects
603
assert(!mAbstractDb);
604
assert(!mRuntimeAbstractDb);
607
mProxyConfig->getConfigValue("MySQLServer", mySQLServer);
608
if(!mySQLServer.empty())
610
mAbstractDb = new MySqlDb(mySQLServer,
611
mProxyConfig->getConfigData("MySQLUser", ""),
612
mProxyConfig->getConfigData("MySQLPassword", ""),
613
mProxyConfig->getConfigData("MySQLDatabaseName", ""),
614
mProxyConfig->getConfigUnsignedLong("MySQLPort", 0),
615
mProxyConfig->getConfigData("MySQLCustomUserAuthQuery", ""));
617
Data runtimeMySQLServer;
618
mProxyConfig->getConfigValue("RuntimeMySQLServer", runtimeMySQLServer);
619
if(!runtimeMySQLServer.empty())
621
mRuntimeAbstractDb = new MySqlDb(runtimeMySQLServer,
622
mProxyConfig->getConfigData("RuntimeMySQLUser", ""),
623
mProxyConfig->getConfigData("RuntimeMySQLPassword", ""),
624
mProxyConfig->getConfigData("RuntimeMySQLDatabaseName", ""),
625
mProxyConfig->getConfigUnsignedLong("RuntimeMySQLPort", 0),
626
mProxyConfig->getConfigData("MySQLCustomUserAuthQuery", ""));
631
mAbstractDb = new BerkeleyDb(mProxyConfig->getConfigData("DatabasePath", "./", true));
634
if(!mAbstractDb->isSane())
636
CritLog(<<"Failed to open configuration database");
640
if(mRuntimeAbstractDb && !mRuntimeAbstractDb->isSane())
642
CritLog(<<"Failed to open runtime configuration database");
646
mProxyConfig->createDataStore(mAbstractDb, mRuntimeAbstractDb);
648
// Create ImMemory Registration Database
649
mRegSyncPort = mProxyConfig->getConfigInt("RegSyncPort", 0);
650
// We only need removed records to linger if we have reg sync enabled
651
if(!mRestarting) // If we are restarting then we left the InMemoryRegistrationDb intact at shutdown - don't recreate
653
assert(!mRegistrationPersistenceManager);
654
mRegistrationPersistenceManager = new InMemorySyncRegDb(mRegSyncPort ? 86400 /* 24 hours */ : 0 /* removeLingerSecs */); // !slg! could make linger time a setting
656
assert(mRegistrationPersistenceManager);
658
// Copy contacts from the StaticRegStore to the RegistrationPersistanceManager
659
populateRegistrations();
665
ReproRunner::createDialogUsageManager()
667
// Create Profile settings for DUM Instance that handles ServerRegistration,
668
// and potentially certificate subscription server
669
SharedPtr<MasterProfile> profile(new MasterProfile);
670
profile->clearSupportedMethods();
671
profile->addSupportedMethod(resip::REGISTER);
673
profile->addSupportedScheme(Symbols::Sips);
675
if(InteropHelper::getOutboundSupported())
677
profile->addSupportedOptionTag(Token(Symbols::Outbound));
679
profile->addSupportedOptionTag(Token(Symbols::Path));
680
if(mProxyConfig->getConfigBool("AllowBadReg", false))
682
profile->allowBadRegistrationEnabled() = true;
685
// Create DialogeUsageManager if Registrar or Certificate Server are enabled
689
mRegistrar = new Registrar;
690
resip::MessageFilterRuleList ruleList;
691
bool registrarEnabled = !mProxyConfig->getConfigBool("DisableRegistrar", false);
692
bool certServerEnabled = mProxyConfig->getConfigBool("EnableCertServer", false);
693
if (registrarEnabled || certServerEnabled)
695
mDum = new DialogUsageManager(*mSipStack);
696
mDum->setMasterProfile(profile);
697
addDomains(*mDum, false /* log? already logged when adding to Proxy - no need to log again*/);
700
// If registrar is enabled, configure DUM to handle REGISTER requests
701
if (registrarEnabled)
704
assert(mRegistrationPersistenceManager);
705
mDum->setServerRegistrationHandler(mRegistrar);
706
mDum->setRegistrationPersistenceManager(mRegistrationPersistenceManager);
708
// Install rules so that the registrar only gets REGISTERs
709
resip::MessageFilterRule::MethodList methodList;
710
methodList.push_back(resip::REGISTER);
711
ruleList.push_back(MessageFilterRule(resip::MessageFilterRule::SchemeList(),
712
resip::MessageFilterRule::DomainIsMe,
716
// If Certificate Server is enabled, configure DUM to handle SUBSCRIBE and
717
// PUBLISH requests for events: credential and certificate
718
assert(!mCertServer);
719
if (certServerEnabled)
722
mCertServer = new CertServer(*mDum);
724
// Install rules so that the cert server receives SUBSCRIBEs and PUBLISHs
725
resip::MessageFilterRule::MethodList methodList;
726
resip::MessageFilterRule::EventList eventList;
727
methodList.push_back(resip::SUBSCRIBE);
728
methodList.push_back(resip::PUBLISH);
729
eventList.push_back(resip::Symbols::Credential);
730
eventList.push_back(resip::Symbols::Certificate);
731
ruleList.push_back(MessageFilterRule(resip::MessageFilterRule::SchemeList(),
732
resip::MessageFilterRule::DomainIsMe,
740
bool enableCertAuth = mProxyConfig->getConfigBool("EnableCertificateAuthenticator", false);
741
// Maintains existing behavior for non-TLS cert auth users
742
bool digestChallengeThirdParties = !enableCertAuth;
746
// TODO: perhaps this should be initialised from the trusted node
747
// monkey? Or should the list of trusted TLS peers be independent
748
// from the trusted node list?
749
std::set<Data> trustedPeers;
750
loadCommonNameMappings();
751
SharedPtr<TlsPeerAuthManager> certAuth(new TlsPeerAuthManager(*mDum, mDum->dumIncomingTarget(), trustedPeers, true, mCommonNameMappings));
752
mDum->addIncomingFeature(certAuth);
755
mSipAuthDisabled = mProxyConfig->getConfigBool("DisableAuth", false);
757
// If Authentication is enabled, then configure DUM to authenticate requests
758
if (!mSipAuthDisabled)
760
// Create UserAuthGrabber Worker Thread Pool if auth is enabled
761
assert(!mAuthRequestDispatcher);
762
int numAuthGrabberWorkerThreads = mProxyConfig->getConfigInt("NumAuthGrabberWorkerThreads", 2);
763
if(numAuthGrabberWorkerThreads < 1) numAuthGrabberWorkerThreads = 1; // must have at least one thread
764
std::auto_ptr<Worker> grabber(new UserAuthGrabber(mProxyConfig->getDataStore()->mUserStore));
765
mAuthRequestDispatcher = new Dispatcher(grabber, mSipStack, numAuthGrabberWorkerThreads);
767
SharedPtr<ServerAuthManager>
768
uasAuth( new ReproServerAuthManager(*mDum,
769
mAuthRequestDispatcher,
770
mProxyConfig->getDataStore()->mAclStore,
771
!mProxyConfig->getConfigBool("DisableAuthInt", false) /*useAuthInt*/,
772
mProxyConfig->getConfigBool("RejectBadNonces", false),
773
digestChallengeThirdParties));
774
mDum->setServerAuthManager(uasAuth);
777
// Set the MessageFilterRuleList on DUM and create a thread to run DUM in
778
mDum->setMessageFilterRuleList(ruleList);
779
mDumThread = new DumThread(*mDum);
784
ReproRunner::createProxy()
786
// Create AsyncProcessorDispatcher thread pool that is shared by the processsors for
787
// any asyncronous tasks (ie: RequestFilter and MessageSilo processors)
788
int numAsyncProcessorWorkerThreads = mProxyConfig->getConfigInt("NumAsyncProcessorWorkerThreads", 2);
789
if(numAsyncProcessorWorkerThreads > 0)
791
assert(!mAsyncProcessorDispatcher);
792
mAsyncProcessorDispatcher = new Dispatcher(std::auto_ptr<Worker>(new AsyncProcessorWorker),
794
numAsyncProcessorWorkerThreads);
797
// Create proxy processor chains
798
/* Explanation: "Monkeys" are processors which operate on incoming requests
799
"Lemurs" are processors which operate on incoming responses
800
"Baboons" are processors which operate on a request for each target
801
as the request is about to be forwarded to that target */
804
mMonkeys = new ProcessorChain(Processor::REQUEST_CHAIN);
805
makeRequestProcessorChain(*mMonkeys);
806
InfoLog(<< *mMonkeys);
810
mLemurs = new ProcessorChain(Processor::RESPONSE_CHAIN);
811
makeResponseProcessorChain(*mLemurs);
812
InfoLog(<< *mLemurs);
816
mBaboons = new ProcessorChain(Processor::TARGET_CHAIN);
817
makeTargetProcessorChain(*mBaboons);
818
InfoLog(<< *mBaboons);
820
// Create main Proxy class
822
mProxy = new Proxy(*mSipStack,
827
mHttpRealm = addDomains(*mProxy, true);
829
// Register the Proxy class a stack transaction user
830
// Note: This is done after creating the DialogUsageManager so that it acts
831
// like a catchall and will handle all requests the DUM does not
832
mSipStack->registerTransactionUser(*mProxy);
838
ReproRunner::populateRegistrations()
840
assert(mRegistrationPersistenceManager);
841
assert(mProxyConfig);
842
assert(mProxyConfig->getDataStore());
844
// Copy contacts from the StaticRegStore to the RegistrationPersistanceManager
845
StaticRegStore::StaticRegRecordMap& staticRegList = mProxyConfig->getDataStore()->mStaticRegStore.getStaticRegList();
846
StaticRegStore::StaticRegRecordMap::iterator it = staticRegList.begin();
847
for(; it != staticRegList.end(); it++)
851
Uri aor(it->second.mAor);
853
ContactInstanceRecord rec;
854
rec.mContact = NameAddr(it->second.mContact);
855
rec.mSipPath = NameAddrs(it->second.mPath);
856
rec.mRegExpires = NeverExpire;
857
rec.mSyncContact = true; // Tag this permanent contact as being a syncronized contact so that it will
858
// be syncronized to a paired server (this is actually configuration information)
859
mRegistrationPersistenceManager->updateContact(aor, rec);
861
catch(resip::ParseBuffer::Exception& e)
863
// This should never happen, since the format should be verified before writing to DB
864
ErrLog(<<"Failed to apply a static registration due to parse error: " << e);
870
ReproRunner::createWebAdmin()
873
assert(!mWebAdminThread);
874
int httpPort = mProxyConfig->getConfigInt("HttpPort", 5080);
877
mWebAdmin = new WebAdmin(*mProxy,
878
*mRegistrationPersistenceManager,
881
if (!mWebAdmin->isSane())
883
CritLog(<<"Failed to start the WebAdmin");
887
mWebAdminThread = new WebAdminThread(*mWebAdmin);
893
ReproRunner::createRegSync()
895
assert(!mRegSyncClient);
896
assert(!mRegSyncServerV4);
897
assert(!mRegSyncServerV6);
898
assert(!mRegSyncServerThread);
899
if(mRegSyncPort != 0)
901
std::list<RegSyncServer*> regSyncServerList;
904
mRegSyncServerV4 = new RegSyncServer(dynamic_cast<InMemorySyncRegDb*>(mRegistrationPersistenceManager), mRegSyncPort, V4);
905
regSyncServerList.push_back(mRegSyncServerV4);
909
mRegSyncServerV6 = new RegSyncServer(dynamic_cast<InMemorySyncRegDb*>(mRegistrationPersistenceManager), mRegSyncPort, V6);
910
regSyncServerList.push_back(mRegSyncServerV6);
912
if(!regSyncServerList.empty())
914
mRegSyncServerThread = new RegSyncServerThread(regSyncServerList);
916
Data regSyncPeerAddress(mProxyConfig->getConfigData("RegSyncPeer", ""));
917
if(!regSyncPeerAddress.empty())
919
mRegSyncClient = new RegSyncClient(dynamic_cast<InMemorySyncRegDb*>(mRegistrationPersistenceManager), regSyncPeerAddress, mRegSyncPort);
925
ReproRunner::createCommandServer()
927
assert(!mCommandServerV4);
928
assert(!mCommandServerV6);
929
assert(!mCommandServerThread);
930
int commandPort = mProxyConfig->getConfigInt("CommandPort", 5081);
933
std::list<CommandServer*> commandServerList;
936
mCommandServerV4 = new CommandServer(*this, commandPort, V4);
937
commandServerList.push_back(mCommandServerV4);
941
mCommandServerV6 = new CommandServer(*this, commandPort, V6);
942
commandServerList.push_back(mCommandServerV6);
944
if(!commandServerList.empty())
946
mCommandServerThread = new CommandServerThread(commandServerList);
952
ReproRunner::addDomains(TransactionUser& tu, bool log)
954
assert(mProxyConfig);
957
std::vector<Data> configDomains;
958
if(mProxyConfig->getConfigValue("Domains", configDomains))
960
for (std::vector<Data>::const_iterator i=configDomains.begin();
961
i != configDomains.end(); ++i)
963
if(log) InfoLog (<< "Adding domain " << *i << " from command line");
972
const ConfigStore::ConfigData& dList = mProxyConfig->getDataStore()->mConfigStore.getConfigs();
973
for (ConfigStore::ConfigData::const_iterator i=dList.begin();
974
i != dList.end(); ++i)
976
if(log) InfoLog (<< "Adding domain " << i->second.mDomain << " from config");
977
tu.addDomain( i->second.mDomain );
980
realm = i->second.mDomain;
984
/* All of this logic has been commented out - the sysadmin must explicitly
985
add any of the items below to the Domains config option in repro.config
987
Data localhostname(DnsUtil::getLocalHostName());
988
if(log) InfoLog (<< "Adding local hostname domain " << localhostname );
989
tu.addDomain(localhostname);
992
realm = localhostname;
995
if(log) InfoLog (<< "Adding localhost domain.");
996
tu.addDomain("localhost");
1002
list<pair<Data,Data> > ips = DnsUtil::getInterfaces();
1003
for ( list<pair<Data,Data> >::const_iterator i=ips.begin(); i!=ips.end(); i++)
1005
if(log) InfoLog( << "Adding domain for IP " << i->second << " from interface " << i->first );
1006
tu.addDomain(i->second);
1009
if(log) InfoLog (<< "Adding 127.0.0.1 domain.");
1010
tu.addDomain("127.0.0.1"); */
1013
realm = "Unconfigured";
1019
ReproRunner::addTransports(bool& allTransportsSpecifyRecordRoute)
1021
assert(mProxyConfig);
1023
allTransportsSpecifyRecordRoute=false;
1024
bool useEmailAsSIP = mProxyConfig->getConfigBool("TLSUseEmailAsSIP", false);
1027
// Check if advanced transport settings are provided
1028
unsigned int transportNum = 1;
1029
Data settingKeyBase("Transport" + Data(transportNum));
1030
Data interfaceSettingKey(settingKeyBase + "Interface");
1031
Data interfaceSettings = mProxyConfig->getConfigData(interfaceSettingKey, "", true);
1032
if(!interfaceSettings.empty())
1034
// Sample config file format for advanced transport settings
1035
// Transport1Interface = 192.168.1.106:5061
1036
// Transport1Type = TLS
1037
// Transport1TlsDomain = sipdomain.com
1038
// Transport1TlsClientVerification = None
1039
// Transport1RecordRouteUri = sip:sipdomain.com;transport=TLS
1040
// Transport1RcvBufLen = 2000
1042
allTransportsSpecifyRecordRoute = true;
1045
while(!interfaceSettings.empty())
1047
Data typeSettingKey(settingKeyBase + "Type");
1048
Data tlsDomainSettingKey(settingKeyBase + "TlsDomain");
1049
Data tlsCVMSettingKey(settingKeyBase + "TlsClientVerification");
1050
Data recordRouteUriSettingKey(settingKeyBase + "RecordRouteUri");
1051
Data rcvBufSettingKey(settingKeyBase + "RcvBufLen");
1053
// Parse out interface settings
1054
ParseBuffer pb(interfaceSettings);
1055
anchor = pb.position();
1061
pb.data(ipAddr, anchor);
1063
anchor = pb.position();
1065
pb.data(portData, anchor);
1066
if(!DnsUtil::isIpAddress(ipAddr))
1068
CritLog(<< "Malformed IP-address found in " << interfaceSettingKey << " setting: " << ipAddr);
1070
int port = portData.convertInt();
1073
CritLog(<< "Invalid port found in " << interfaceSettingKey << " setting: " << port);
1075
TransportType tt = Tuple::toTransport(mProxyConfig->getConfigData(typeSettingKey, "UDP"));
1076
if(tt == UNKNOWN_TRANSPORT)
1078
CritLog(<< "Unknown transport type found in " << typeSettingKey << " setting: " << mProxyConfig->getConfigData(typeSettingKey, "UDP"));
1080
Data tlsDomain = mProxyConfig->getConfigData(tlsDomainSettingKey, "");
1081
Data tlsCVMValue = mProxyConfig->getConfigData(tlsCVMSettingKey, "NONE");
1082
SecurityTypes::TlsClientVerificationMode cvm = SecurityTypes::None;
1083
if(isEqualNoCase(tlsCVMValue, "Optional"))
1085
cvm = SecurityTypes::Optional;
1087
else if(isEqualNoCase(tlsCVMValue, "Mandatory"))
1089
cvm = SecurityTypes::Mandatory;
1091
else if(!isEqualNoCase(tlsCVMValue, "None"))
1093
CritLog(<< "Unknown TLS client verification mode found in " << tlsCVMSettingKey << " setting: " << tlsCVMValue);
1095
int rcvBufLen = mProxyConfig->getConfigInt(rcvBufSettingKey, 0);
1096
Transport *t = mSipStack->addTransport(tt,
1098
DnsUtil::isIpV6Address(ipAddr) ? V6 : V4,
1100
ipAddr, // interface to bind to
1102
Data::Empty, // private key passphrase - not currently used
1103
SecurityTypes::TLSv1, // sslType
1104
0, // transport flags
1105
cvm, // tls client verification mode
1108
if (t && rcvBufLen>0 )
1110
#if defined(RESIP_SIPSTACK_HAVE_FDPOLL)
1111
// this new method is part of the epoll changeset,
1112
// which isn't commited yet.
1113
t->setRcvBufLen(rcvBufLen);
1119
Data recordRouteUri = mProxyConfig->getConfigData(recordRouteUriSettingKey, "");
1120
if(!recordRouteUri.empty())
1124
if(isEqualNoCase(recordRouteUri, "auto")) // auto generated record route uri
1126
if(tt == TLS || tt == DTLS)
1129
rr.uri().host()=tlsDomain;
1130
rr.uri().port()=port;
1131
rr.uri().param(resip::p_transport)=resip::Tuple::toDataLower(tt);
1132
t->setRecordRoute(rr);
1133
InfoLog (<< "Transport specific record-route enabled (generated): " << rr);
1138
rr.uri().host()=ipAddr;
1139
rr.uri().port()=port;
1140
rr.uri().param(resip::p_transport)=resip::Tuple::toDataLower(tt);
1141
t->setRecordRoute(rr);
1142
InfoLog (<< "Transport specific record-route enabled (generated): " << rr);
1147
NameAddr rr(recordRouteUri);
1148
t->setRecordRoute(rr);
1149
InfoLog (<< "Transport specific record-route enabled: " << rr);
1152
catch(BaseException& e)
1154
ErrLog (<< "Invalid uri provided in " << recordRouteUriSettingKey << " setting (ignoring): " << e);
1155
allTransportsSpecifyRecordRoute = false;
1160
allTransportsSpecifyRecordRoute = false;
1165
CritLog(<< "Port not specified in " << interfaceSettingKey << " setting: expected format is <IPAddress>:<Port>");
1169
// Check if there is another transport
1171
settingKeyBase = Data("Transport" + Data(transportNum));
1172
interfaceSettingKey = Data(settingKeyBase + "Interface");
1173
interfaceSettings = mProxyConfig->getConfigData(interfaceSettingKey, "", true);
1178
int udpPort = mProxyConfig->getConfigInt("UDPPort", 5060);
1179
int tcpPort = mProxyConfig->getConfigInt("TCPPort", 5060);
1180
int tlsPort = mProxyConfig->getConfigInt("TLSPort", 5061);
1181
int dtlsPort = mProxyConfig->getConfigInt("DTLSPort", 0);
1182
Data tlsDomain = mProxyConfig->getConfigData("TLSDomainName", "");
1183
Data tlsCVMValue = mProxyConfig->getConfigData("TLSClientVerification", "NONE");
1184
SecurityTypes::TlsClientVerificationMode cvm = SecurityTypes::None;
1185
if(isEqualNoCase(tlsCVMValue, "Optional"))
1187
cvm = SecurityTypes::Optional;
1189
else if(isEqualNoCase(tlsCVMValue, "Mandatory"))
1191
cvm = SecurityTypes::Mandatory;
1193
else if(!isEqualNoCase(tlsCVMValue, "None"))
1195
CritLog(<< "Unknown TLS client verification mode found in TLSClientVerification setting: " << tlsCVMValue);
1200
if (mUseV4) mSipStack->addTransport(UDP, udpPort, V4, StunEnabled);
1201
if (mUseV6) mSipStack->addTransport(UDP, udpPort, V6, StunEnabled);
1205
if (mUseV4) mSipStack->addTransport(TCP, tcpPort, V4, StunEnabled);
1206
if (mUseV6) mSipStack->addTransport(TCP, tcpPort, V6, StunEnabled);
1210
if (mUseV4) mSipStack->addTransport(TLS, tlsPort, V4, StunEnabled, Data::Empty, tlsDomain, Data::Empty, SecurityTypes::TLSv1, 0, cvm, useEmailAsSIP);
1211
if (mUseV6) mSipStack->addTransport(TLS, tlsPort, V6, StunEnabled, Data::Empty, tlsDomain, Data::Empty, SecurityTypes::TLSv1, 0, cvm, useEmailAsSIP);
1215
if (mUseV4) mSipStack->addTransport(DTLS, dtlsPort, V4, StunEnabled, Data::Empty, tlsDomain);
1216
if (mUseV6) mSipStack->addTransport(DTLS, dtlsPort, V6, StunEnabled, Data::Empty, tlsDomain);
1220
catch (BaseException& e)
1222
std::cerr << "Likely a port is already in use" << endl;
1223
InfoLog (<< "Caught: " << e);
1230
ReproRunner::addProcessor(repro::ProcessorChain& chain, std::auto_ptr<Processor> processor)
1232
chain.addProcessor(processor);
1236
ReproRunner::loadCommonNameMappings()
1239
if(!mCommonNameMappings.empty())
1242
Data mappingsFileName = mProxyConfig->getConfigData("CommonNameMappings", "");
1243
if(mappingsFileName.empty())
1246
InfoLog(<< "trying to load common name mappings from file: " << mappingsFileName);
1248
ifstream mappingsFile(mappingsFileName.c_str());
1251
throw std::runtime_error("Error opening/reading mappings file");
1255
while(getline(mappingsFile, sline))
1259
PermittedFromAddresses permitted;
1260
ParseBuffer pb(line);
1262
pb.skipWhitespace();
1263
const char * anchor = pb.position();
1264
if(pb.eof() || *anchor == '#') continue; // if line is a comment or blank then skip it
1266
// Look for end of name
1267
pb.skipToOneOf("\t");
1268
pb.data(cn, anchor);
1273
pb.skipWhitespace();
1278
anchor = pb.position();
1279
pb.skipToOneOf(",\r\n ");
1280
pb.data(value, anchor);
1283
StackLog(<< "Loading CN '" << cn << "', found mapping '" << value << "'");
1284
permitted.insert(value);
1290
DebugLog(<< "Loaded mapping for CN '" << cn << "', " << permitted.size() << " mapping(s)");
1291
mCommonNameMappings[cn] = permitted;
1296
ReproRunner::makeRequestProcessorChain(ProcessorChain& chain)
1298
assert(mProxyConfig);
1299
assert(mRegistrationPersistenceManager);
1301
// Add strict route fixup monkey
1302
addProcessor(chain, std::auto_ptr<Processor>(new StrictRouteFixup));
1304
// Add is trusted node monkey
1305
addProcessor(chain, std::auto_ptr<Processor>(new IsTrustedNode(*mProxyConfig)));
1307
// Add Certificate Authenticator - if required
1308
if(mProxyConfig->getConfigBool("EnableCertificateAuthenticator", false))
1310
// TODO: perhaps this should be initialised from the trusted node
1311
// monkey? Or should the list of trusted TLS peers be independent
1312
// from the trusted node list?
1313
// Should we used the same trustedPeers object that was
1314
// passed to TlsPeerAuthManager perhaps?
1315
std::set<Data> trustedPeers;
1316
loadCommonNameMappings();
1317
addProcessor(chain, std::auto_ptr<Processor>(new CertificateAuthenticator(*mProxyConfig, mSipStack, trustedPeers, true, mCommonNameMappings)));
1320
// Add digest authenticator monkey - if required
1321
if (!mSipAuthDisabled)
1323
assert(mAuthRequestDispatcher);
1324
DigestAuthenticator* da = new DigestAuthenticator(*mProxyConfig, mAuthRequestDispatcher);
1326
addProcessor(chain, std::auto_ptr<Processor>(da));
1329
// Add am I responsible monkey
1330
addProcessor(chain, std::auto_ptr<Processor>(new AmIResponsible));
1332
// Add RequestFilter monkey
1333
if(!mProxyConfig->getConfigBool("DisableRequestFilterProcessor", false))
1335
if(mAsyncProcessorDispatcher)
1337
addProcessor(chain, std::auto_ptr<Processor>(new RequestFilter(*mProxyConfig, mAsyncProcessorDispatcher)));
1341
WarningLog(<< "Could not start RequestFilter Processor due to no worker thread pool (NumAsyncProcessorWorkerThreads=0)");
1345
// [TODO] support for GRUU is on roadmap. When it is added the GruuMonkey will go here
1347
// [TODO] support for Manipulating Tel URIs is on the roadmap.
1348
// When added, the telUriMonkey will go here
1350
std::vector<Data> routeSet;
1351
mProxyConfig->getConfigValue("Routes", routeSet);
1352
if (routeSet.empty())
1354
// add static route monkey
1355
addProcessor(chain, std::auto_ptr<Processor>(new StaticRoute(*mProxyConfig)));
1359
// add simple static route monkey
1360
addProcessor(chain, std::auto_ptr<Processor>(new SimpleStaticRoute(*mProxyConfig)));
1363
// Add location server monkey
1364
addProcessor(chain, std::auto_ptr<Processor>(new LocationServer(*mProxyConfig, *mRegistrationPersistenceManager, mAuthRequestDispatcher)));
1366
// Add message silo monkey
1367
if(mProxyConfig->getConfigBool("MessageSiloEnabled", false))
1369
if(mAsyncProcessorDispatcher && mRegistrar)
1371
MessageSilo* silo = new MessageSilo(*mProxyConfig, mAsyncProcessorDispatcher);
1372
mRegistrar->addRegistrarHandler(silo);
1373
addProcessor(chain, std::auto_ptr<Processor>(silo));
1377
WarningLog(<< "Could not start MessageSilo Processor due to no worker thread pool (NumAsyncProcessorWorkerThreads=0) or Registrar");
1383
ReproRunner::makeResponseProcessorChain(ProcessorChain& chain)
1385
assert(mProxyConfig);
1386
assert(mRegistrationPersistenceManager);
1388
// Add outbound target handler lemur
1389
addProcessor(chain, std::auto_ptr<Processor>(new OutboundTargetHandler(*mRegistrationPersistenceManager)));
1391
if (mProxyConfig->getConfigBool("RecursiveRedirect", false))
1393
// Add recursive redirect lemur
1394
addProcessor(chain, std::auto_ptr<Processor>(new RecursiveRedirect));
1399
ReproRunner::makeTargetProcessorChain(ProcessorChain& chain)
1401
assert(mProxyConfig);
1403
#ifndef RESIP_FIXED_POINT
1404
if(mProxyConfig->getConfigBool("GeoProximityTargetSorting", false))
1406
addProcessor(chain, std::auto_ptr<Processor>(new GeoProximityTargetSorter(*mProxyConfig)));
1410
if(mProxyConfig->getConfigBool("QValue", true))
1412
// Add q value target handler baboon
1413
addProcessor(chain, std::auto_ptr<Processor>(new QValueTargetHandler(*mProxyConfig)));
1416
// Add simple target handler baboon
1417
addProcessor(chain, std::auto_ptr<Processor>(new SimpleTargetHandler));
1421
/* ====================================================================
1422
* The Vovida Software License, Version 1.0
1424
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
1426
* Redistribution and use in source and binary forms, with or without
1427
* modification, are permitted provided that the following conditions
1430
* 1. Redistributions of source code must retain the above copyright
1431
* notice, this list of conditions and the following disclaimer.
1433
* 2. Redistributions in binary form must reproduce the above copyright
1434
* notice, this list of conditions and the following disclaimer in
1435
* the documentation and/or other materials provided with the
1438
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
1439
* and "Vovida Open Communication Application Library (VOCAL)" must
1440
* not be used to endorse or promote products derived from this
1441
* software without prior written permission. For written
1442
* permission, please contact vocal@vovida.org.
1444
* 4. Products derived from this software may not be called "VOCAL", nor
1445
* may "VOCAL" appear in their name, without prior written
1446
* permission of Vovida Networks, Inc.
1448
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1449
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1450
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1451
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
1452
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1453
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1454
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1455
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1456
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1457
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1458
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1459
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1462
* ====================================================================