reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
ReproRunner.cxx
Go to the documentation of this file.
1#if defined(HAVE_CONFIG_H)
2#include "config.h"
3#endif
4
5#include <iostream>
6#include <fstream>
7#include <stdexcept>
8#include <utility>
9#ifndef WIN32
10#include <syslog.h>
11#endif
12
13#include "rutil/ResipAssert.h"
14#include "rutil/Log.hxx"
15#include "rutil/Logger.hxx"
16#include "rutil/DnsUtil.hxx"
17#include "rutil/dns/DnsStub.hxx"
21
31
39
41#include "repro/ReproRunner.hxx"
42#include "repro/Proxy.hxx"
43#include "repro/ProxyConfig.hxx"
44#include "repro/BerkeleyDb.hxx"
49#include "repro/WebAdmin.hxx"
51#include "repro/Registrar.hxx"
77
78#if defined(USE_SSL)
81#define DEFAULT_TLS_METHOD SecurityTypes::DynamicTLS
82#endif
83
84#if defined(USE_MYSQL)
85#include "repro/MySqlDb.hxx"
86#endif
87
88#if defined(USE_POSTGRESQL)
90#endif
91
93
94#define RESIPROCATE_SUBSYSTEM resip::Subsystem::REPRO
95
96using namespace resip;
97using namespace repro;
98using namespace std;
99
101{
102public:
103 virtual ~ReproLogger() {}
105 virtual bool operator()(Log::Level level,
106 const Subsystem& subsystem,
107 const Data& appName,
108 const char* file,
109 int line,
110 const Data& message,
111 const Data& messageWithHeaders,
112 const Data& instanceName)
113 {
114 // Log any errors to the screen
115 if(level <= Log::Err)
116 {
117 resipCout << messageWithHeaders << endl;
118 }
119 return true;
120 }
121};
123
125{
126public:
128 virtual void outboundMessage(const Tuple &source, const Tuple &destination, const SipMessage &msg)
129 {
130 InfoLog(<< "\r\n*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*\r\n"
131 << "OUTBOUND: Src=" << source << ", Dst=" << destination << "\r\n\r\n"
132 << msg
133 << "*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*");
134 }
135 virtual void outboundRetransmit(const Tuple &source, const Tuple &destination, const SendData &data)
136 {
137 InfoLog(<< "\r\n*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*\r\n"
138 << "OUTBOUND(retransmit): Src=" << source << ", Dst=" << destination << "\r\n\r\n"
139 << data.data
140 << "*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*");
141 }
142 virtual void inboundMessage(const Tuple& source, const Tuple& destination, const SipMessage &msg)
143 {
144 InfoLog(<< "\r\n*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*v*\r\n"
145 << "INBOUND: Src=" << source << ", Dst=" << destination << "\r\n\r\n"
146 << msg
147 << "*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*");
148 }
149};
150
152{
153public:
154 AbstractDb *getDatabase(int configIndex)
155 {
157 ConfigParse::NestedConfigMap::iterator it = m.find(configIndex);
158 if (it == m.end())
159 {
160 WarningLog(<< "Failed to find Database settings for index " << configIndex);
161 return 0;
162 }
163 ConfigParse& dbConfig = it->second;
164 Data dbType = dbConfig.getConfigData("Type", "");
165 dbType.lowercase();
166 if (dbType == "berkeleydb")
167 {
168 Data path = dbConfig.getConfigData("Path",
169 getConfigData("DatabasePath", "./", true), true);
170 return new BerkeleyDb(path);
171 }
172 else if (dbType == "mysql")
173 {
174#ifdef USE_MYSQL
175 Data mySQLServer = dbConfig.getConfigData("Host", Data::Empty);
176 if (!mySQLServer.empty())
177 {
178 return new MySqlDb(dbConfig, mySQLServer,
179 dbConfig.getConfigData("User", Data::Empty),
180 dbConfig.getConfigData("Password", Data::Empty),
181 dbConfig.getConfigData("DatabaseName", Data::Empty),
182 dbConfig.getConfigUnsignedLong("Port", 0),
183 dbConfig.getConfigData("CustomUserAuthQuery", Data::Empty));
184 }
185#else
186 ErrLog(<< "Database" << configIndex << " type MySQL support not compiled into repro");
187 return 0;
188#endif
189 }
190 else if (dbType == "postgresql")
191 {
192#ifdef USE_POSTGRESQL
193 Data postgreSQLConnInfo = dbConfig.getConfigData("ConnInfo", Data::Empty);
194 Data postgreSQLServer = dbConfig.getConfigData("Host", Data::Empty);
195 if (!postgreSQLConnInfo.empty() || !postgreSQLServer.empty())
196 {
197 return new PostgreSqlDb(dbConfig, postgreSQLConnInfo, postgreSQLServer,
198 dbConfig.getConfigData("User", Data::Empty),
199 dbConfig.getConfigData("Password", Data::Empty),
200 dbConfig.getConfigData("DatabaseName", Data::Empty),
201 dbConfig.getConfigUnsignedLong("Port", 0),
202 dbConfig.getConfigData("CustomUserAuthQuery", Data::Empty));
203 }
204#else
205 ErrLog(<< "Database" << configIndex << " type PostgreSQL support not compiled into repro");
206 return 0;
207#endif
208 }
209 else
210 {
211 ErrLog(<< "Database" << configIndex << " type '" << dbType << "' not supported / invalid");
212 }
213 return 0;
214 }
215};
216
218 : mRunning(false)
219 , mRestarting(false)
220 , mThreadedStack(false)
221 , mUseV4(true)
222 , mUseV6 (false)
223 , mRegSyncPort(0)
224 , mProxyConfig(0)
225 , mFdPollGrp(0)
226 , mAsyncProcessHandler(0)
227 , mSipStack(0)
228 , mStackThread(0)
229 , mAbstractDb(0)
230 , mRuntimeAbstractDb(0)
231 , mRegistrationPersistenceManager(0)
232 , mPublicationPersistenceManager(0)
233 , mAuthFactory(0)
234 , mAsyncProcessorDispatcher(0)
235 , mMonkeys(0)
236 , mLemurs(0)
237 , mBaboons(0)
238 , mProxy(0)
239 , mWebAdminThread(0)
240 , mRegistrar(0)
241 , mPresenceServer(0)
242 , mDum(0)
243 , mDumThread(0)
244 , mCertServer(0)
245 , mRegSyncClient(0)
246 , mRegSyncServerV4(0)
247 , mRegSyncServerV6(0)
248 , mRegSyncServerAMQP(0)
249 , mRegSyncServerThread(0)
250 , mCommandServerThread(0)
251 , mCongestionManager(0)
252{
253}
254
259
260bool
261ReproRunner::run(int argc, char** argv)
262{
263 if(mRunning) return false;
264
266
267 if(!mRestarting)
268 {
269 // Store original arc and argv - so we can reuse them on restart request
270 mArgc = argc;
271 mArgv = argv;
272 }
273
274 // Parse command line and configuration file
276 Data defaultConfigFilename("repro.config");
277 try
278 {
280 mProxyConfig->parseConfig(mArgc, mArgv, defaultConfigFilename);
281 }
282 catch(BaseException& ex)
283 {
284 std::cerr << "Error parsing configuration: " << ex << std::endl;
285#ifndef WIN32
286 syslog(LOG_DAEMON | LOG_CRIT, "%s", ex.getMessage().c_str());
287#endif
288 return false;
289 }
290
291 // Non-Windows server process stuff
292 if(!mRestarting)
293 {
294 Data pidFile = mProxyConfig->getConfigData("PidFile", Data::Empty, true);
295 if(!pidFile.empty() && checkPosixProcessControl("PidFile"))
296 {
297 setPidFile(pidFile);
298 }
299
300 if(isAlreadyRunning())
301 {
302 std::cerr << "Already running, will not start two instances. Please stop existing process and/or delete PID file.";
303#ifndef WIN32
304 syslog(LOG_DAEMON | LOG_CRIT, "Already running, will not start two instances. Please stop existing process and/or delete PID file.");
305#endif
306 return false;
307 }
308
309 if(mProxyConfig->getConfigBool("Daemonize", false) && checkPosixProcessControl("Daemonize"))
310 {
311 daemonize();
312 }
313 }
314
315 // Initialize resip logger
316 Data loggingType = mProxyConfig->getConfigData("LoggingType", "cout", true);
319 mArgv[0],
320 isEqualNoCase(loggingType, "file") ? &g_ReproLogger : 0);
321
322 InfoLog( << "Starting repro version " << VersionUtils::instance().releaseVersion() << "...");
323
324 // Create SipStack and associated objects
325 if(!createSipStack())
326 {
327 return false;
328 }
329
330 // Load the plugins after creating the stack, as they may need it
331 if(!loadPlugins())
332 {
333 return false;
334 }
335
336 // Drop privileges (can do this now that sockets are bound)
337 Data runAsUser = mProxyConfig->getConfigData("RunAsUser", Data::Empty, true);
338 Data runAsGroup = mProxyConfig->getConfigData("RunAsGroup", Data::Empty, true);
339 if(!runAsUser.empty() && checkPosixProcessControl("RunAsUser/RunAsGroup"))
340 {
341 InfoLog( << "Trying to drop privileges, configured uid = " << runAsUser << " gid = " << runAsGroup);
342 dropPrivileges(runAsUser, runAsGroup);
343 }
344
345 // Create datastore
346 if(!createDatastore())
347 {
348 return false;
349 }
350
351 // Create authentication mechanism
353
354 // Create DialogUsageManager that handles ServerRegistration,
355 // and potentially certificate subscription server
357
358 // Create the Proxy and associate objects
359 if(!createProxy())
360 {
361 return false;
362 }
363
364 // Create HTTP WebAdmin and Thread
365 if(!createWebAdmin())
366 {
367 return false;
368 }
369
370 // Create reg sync components if required
372
373 // Create command server if required
374 if(!mRestarting)
375 {
377 }
378
379 // Make it all go - startup all threads
380 mThreadedStack = mProxyConfig->getConfigBool("ThreadedStack", true);
382 {
383 // If configured, then start the sub-threads within the stack
384 mSipStack->run();
385 }
386 mStackThread->run();
387 if(mDumThread)
388 {
389 mDumThread->run();
390 }
391 mProxy->run();
393 {
395 }
397 {
399 }
401 {
403 }
405 {
407 }
408
409 mRunning = true;
410
411 return true;
412}
413
414void
416{
417 if(!mRunning) return;
418
419 // Tell all threads to shutdown
421 {
423 }
424 if(mDumThread)
425 {
427 }
428 mProxy->shutdown();
430 if(!mRestarting && mCommandServerThread) // leave command server running if we are restarting
431 {
433 }
435 {
437 }
439 {
441 }
442
443 // Wait for all threads to shutdown, and destroy objects
444 mProxy->join();
446 {
448 }
450 if(mWebAdminThread)
451 {
453 }
454 if(mDumThread)
455 {
456 mDumThread->join();
457 }
458 if(mAuthFactory)
459 {
460 // Both proxy and dum threads are down at this point, we can
461 // destroy the authFactory and its authRequest dispatcher
462 // and associated threads now
463 delete mAuthFactory;
464 mAuthFactory = 0;
465 }
467 {
468 // Both proxy and dum threads are down at this point, we can
469 // destroy the async processor dispatcher and associated threads now
472 }
473 if(!mRestarting && mCommandServerThread) // we leave command server running during restart
474 {
476 }
478 {
480 }
482 {
484 }
485
487
489 mRunning = false;
490}
491
492void
494{
495 if(!mRunning) return;
496 mRestarting = true;
497 shutdown();
498 run(0, 0);
499 mRestarting = false;
500}
501
502void
504{
506 // Let the plugins know
507#ifdef DSO_PLUGINS
508 if(mPluginManager)
509 {
510 mPluginManager->onReload();
511 }
512#endif
513}
514
515void
517{
518 if(!mRestarting)
519 {
520 // We leave command server running during restart
522 for(std::list<CommandServer*>::iterator it = mCommandServerList.begin(); it != mCommandServerList.end(); it++)
523 {
524 delete (*it);
525 }
526 mCommandServerList.clear();
527 }
532 delete mRegSyncClient; mRegSyncClient = 0;
533#if defined(USE_SSL)
534 delete mCertServer; mCertServer = 0;
535#endif
536 delete mDumThread; mDumThread = 0;
537 delete mDum; mDum = 0;
538 delete mRegistrar; mRegistrar = 0;
541 for(std::list<WebAdmin*>::iterator it = mWebAdminList.begin(); it != mWebAdminList.end(); it++)
542 {
543 delete (*it);
544 }
545 mWebAdminList.clear();
546 delete mProxy; mProxy = 0;
547 delete mBaboons; mBaboons = 0;
548 delete mLemurs; mLemurs = 0;
549 delete mMonkeys; mMonkeys = 0;
550 delete mAuthFactory; mAuthFactory = 0;
552 if(!mRestarting)
553 {
554 // If we are restarting then leave the In Memory Registration and Publication database intact
557 }
558 delete mAbstractDb; mAbstractDb = 0;
560 delete mStackThread; mStackThread = 0;
561 delete mSipStack; mSipStack = 0;
564 delete mFdPollGrp; mFdPollGrp = 0;
565 delete mProxyConfig; mProxyConfig = 0;
566}
567
568bool
570{
571 std::vector<Data> pluginNames;
572 mProxyConfig->getConfigValue("LoadPlugins", pluginNames);
573
574#ifdef DSO_PLUGINS
575 mPluginManager.reset(new ReproPluginManager(*mSipStack, mProxyConfig));
576 return mPluginManager->loadPlugins(pluginNames);
577#else
578 if (pluginNames.empty()) return true;
579
580 CritLog(<< "LoadPlugins is specified in the configuration but repro was compiled without plugin support");
581 return false;
582#endif
583}
584
585void
587{
588#ifdef USE_SSL
589 std::set<Data> values;
590 if(mProxyConfig->getConfigValue(configVar, values))
591 {
592 opts = 0;
593 for(std::set<Data>::iterator it = values.begin();
594 it != values.end(); it++)
595 {
596 opts |= Security::parseOpenSSLCTXOption(*it);
597 }
598 }
599#endif
600}
601
602bool
604{
605 // Override T1 timer if configured to do so
606 unsigned long overrideT1 = mProxyConfig->getConfigUnsignedLong("TimerT1", 0);
607 if(overrideT1)
608 {
609 WarningLog(<< "Overriding T1! (new value is " << overrideT1 << ")");
610 resip::Timer::resetT1(overrideT1);
611 }
612
613 // Set TCP Connect timeout
614 resip::Timer::TcpConnectTimeout = mProxyConfig->getConfigUnsignedLong("TCPConnectTimeout", 10000); // Default to 10 seconds
615
616 // Set DNS Greylist Duration
617 resip::TransactionState::DnsGreylistDurationMs = mProxyConfig->getConfigUnsignedLong("DNSGreylistDuration", 1800000); // Default to 30mins
618
619 unsigned long messageSizeLimit = mProxyConfig->getConfigUnsignedLong("StreamMessageSizeLimit", 0);
620 if(messageSizeLimit > 0)
621 {
622 DebugLog(<< "Using maximum message size "<< messageSizeLimit << " on stream-based transports");
623 ConnectionBase::setMessageSizeMax(messageSizeLimit);
624 }
625
626 // Create Security (TLS / Certificates) and Compression (SigComp) objects if
627 // pre-precessor defines are enabled
628 Security* security = 0;
629 Compression* compression = 0;
630#ifdef USE_SSL
632 "OpenSSLCTXSetOptions", BaseSecurity::OpenSSLCTXSetOptions);
634 "OpenSSLCTXClearOptions", BaseSecurity::OpenSSLCTXClearOptions);
635 Security::CipherList cipherList = Security::StrongestSuite;
636 Data ciphers = mProxyConfig->getConfigData("OpenSSLCipherList", Data::Empty);
637 if(!ciphers.empty())
638 {
639 cipherList = ciphers;
640 }
641 Data certPath = mProxyConfig->getConfigData("CertificatePath", Data::Empty);
642 Data dHParamsFilename = mProxyConfig->getConfigData("TlsDHParamsFilename", Data::Empty);
643 if(certPath.empty())
644 {
645 security = new Security(cipherList, mProxyConfig->getConfigData("TLSPrivateKeyPassPhrase", Data::Empty), dHParamsFilename);
646 }
647 else
648 {
649 security = new Security(certPath, cipherList, mProxyConfig->getConfigData("TLSPrivateKeyPassPhrase", Data::Empty), dHParamsFilename);
650 }
651 std::vector<Data> caDirNames;
652 mProxyConfig->getConfigValue("CADirectory", caDirNames);
653 for(std::vector<Data>::const_iterator caDir = caDirNames.begin();
654 caDir != caDirNames.end(); caDir++)
655 {
656 security->addCADirectory(*caDir);
657 }
658 std::vector<Data> caFileNames;
659 mProxyConfig->getConfigValue("CAFile", caFileNames);
660 for(std::vector<Data>::const_iterator caFile = caFileNames.begin();
661 caFile != caFileNames.end(); caFile++)
662 {
663 security->addCAFile(*caFile);
664 }
665 BaseSecurity::setAllowWildcardCertificates(mProxyConfig->getConfigBool("AllowWildcardCertificates", false));
666#endif
667
668#ifdef USE_SIGCOMP
669 compression = new Compression(Compression::DEFLATE);
670#endif
671
672 // Create EventThreadInterruptor used to wake up the stack for
673 // for reasons other than an Fd signalling
678
679 // Set Flags that will enable/disable IPv4 and/or IPv6, based on
680 // configuration and pre-processor flags
681 mUseV4 = !mProxyConfig->getConfigBool("DisableIPv4", false);
682#ifdef USE_IPV6
683 mUseV6 = mProxyConfig->getConfigBool("EnableIPv6", true);
684#else
685 bool useV6 = false;
686#endif
687 if (mUseV4) InfoLog (<< "V4 enabled");
688 if (mUseV6) InfoLog (<< "V6 enabled");
689
690 // Build DNS Server list from config
691 DnsStub::NameserverList dnsServers;
692 std::vector<resip::Data> dnsServersConfig;
693 mProxyConfig->getConfigValue("DNSServers", dnsServersConfig);
694 for(std::vector<resip::Data>::iterator it = dnsServersConfig.begin(); it != dnsServersConfig.end(); it++)
695 {
697 {
698 InfoLog(<< "Using DNS Server from config: " << *it);
699 dnsServers.push_back(Tuple(*it, 0, UNKNOWN_TRANSPORT).toGenericIPAddress());
700 }
701 }
702
703 // Create the SipStack Object
705 mSipStack = new SipStack(security,
706 dnsServers,
708 /*stateless*/false,
709 /*socketFunc*/0,
710 compression,
711 mFdPollGrp);
712
713 // Set any enum suffixes from configuration
714 std::vector<Data> enumSuffixes;
715 mProxyConfig->getConfigValue("EnumSuffixes", enumSuffixes);
716 if (enumSuffixes.size() > 0)
717 {
718 mSipStack->setEnumSuffixes(enumSuffixes);
719 }
720
721 // Set any enum domains from configuration
722 std::map<Data,Data> enumDomains;
723 std::vector<Data> _enumDomains;
724 mProxyConfig->getConfigValue("EnumDomains", _enumDomains);
725 if (enumSuffixes.size() > 0)
726 {
727 for(std::vector<Data>::iterator it = _enumDomains.begin(); it != _enumDomains.end(); it++)
728 {
729 enumDomains[*it] = *it;
730 }
731 mSipStack->setEnumDomains(enumDomains);
732 }
733
734 // Add External Stats handler
736
737 // Set Transport SipMessage Logging Handler - if enabled
738 Data captureHost;
739 mProxyConfig->getConfigValue("CaptureHost", captureHost);
740 if(!captureHost.empty())
741 {
742 int capturePort = mProxyConfig->getConfigInt("CapturePort", 9060);
743 int captureAgentID = mProxyConfig->getConfigInt("CaptureAgentID", 2001);
744 auto agent = std::make_shared<HepAgent>(captureHost, capturePort, captureAgentID);
745 mSipStack->addTransportSipMessageLoggingHandler(std::make_shared<HEPSipMessageLoggingHandler>(agent));
746 }
747 else if(mProxyConfig->getConfigBool("EnableSipMessageLogging", false))
748 {
749 mSipStack->addTransportSipMessageLoggingHandler(std::make_shared<ReproSipMessageLoggingHandler>());
750 }
751
752 // Add stack transports
753 bool allTransportsSpecifyRecordRoute=false;
754 if(!addTransports(allTransportsSpecifyRecordRoute))
755 {
757 return false;
758 }
759
760 // Enable and configure RFC5626 Outbound support
762 InteropHelper::setOutboundSupported(mProxyConfig->getConfigBool("DisableOutbound", false) ? false : true);
764 InteropHelper::setAllowInboundFlowTokensForNonDirectClients(mProxyConfig->getConfigBool("AllowInboundFlowTokensForNonDirectClients", false));
767 Data clientNATDetectionMode = mProxyConfig->getConfigData("ClientNatDetectionMode", "DISABLED");
768 if(isEqualNoCase(clientNATDetectionMode, "ENABLED"))
769 {
771 }
772 else if(isEqualNoCase(clientNATDetectionMode, "PRIVATE_TO_PUBLIC"))
773 {
775 }
777 unsigned long tcpConnectionGCAge = mProxyConfig->getConfigUnsignedLong("TCPConnectionGCAge", 0);
778 if(tcpConnectionGCAge > 0)
779 {
780 ConnectionManager::MinimumGcAge = tcpConnectionGCAge * 1000;
782 }
783 unsigned long outboundFlowTimer = mProxyConfig->getConfigUnsignedLong("FlowTimer", 0);
784 if(outboundFlowTimer > 0)
785 {
786 InteropHelper::setFlowTimerSeconds(outboundFlowTimer);
787 if(tcpConnectionGCAge == 0)
788 {
789 // This should be set too when using outboundFlowTimer
791 }
793 }
794
795 // Decide whether or not to add rport to the Via header
797
798 // Check Path and RecordRoute settings, print warning if features are enabled that
799 // require record-routing and record-route uri(s) is not configured
800 bool forceRecordRoute = mProxyConfig->getConfigBool("ForceRecordRouting", false);
801 Uri recordRouteUri;
802 mProxyConfig->getConfigValue("RecordRouteUri", recordRouteUri);
806 || forceRecordRoute
807 )
808 && !(allTransportsSpecifyRecordRoute || !recordRouteUri.host().empty()))
809 {
810 CritLog(<< "In order for outbound support, the Record-Route flow-token"
811 " hack, or force-record-route to work, you MUST specify a Record-Route URI. Launching "
812 "without...");
816 forceRecordRoute=false;
817 }
818
819 // Configure misc. stack settings
822 int statsLogInterval = mProxyConfig->getConfigInt("StatisticsLogInterval", 60);
823 if(statsLogInterval > 0)
824 {
825 mSipStack->setStatisticsInterval(statsLogInterval);
827 }
828 else
829 {
831 }
832
833 // Create Congestion Manager, if required
835 if(mProxyConfig->getConfigBool("CongestionManagement", true))
836 {
837 Data metricData = mProxyConfig->getConfigData("CongestionManagementMetric", "WAIT_TIME", true);
839 if(isEqualNoCase(metricData, "TIME_DEPTH"))
840 {
842 }
843 else if(isEqualNoCase(metricData, "SIZE"))
844 {
846 }
847 else if(!isEqualNoCase(metricData, "WAIT_TIME"))
848 {
849 WarningLog( << "CongestionManagementMetric specified as an unknown value (" << metricData << "), defaulting to WAIT_TIME.");
850 }
852 metric,
853 mProxyConfig->getConfigUnsignedLong("CongestionManagementTolerance", 200));
855 }
856
857 // Create base thread to run stack in (note: stack may use other sub-threads, depending on configuration)
861 *mFdPollGrp);
862 return true;
863}
864
865bool
867{
868 // Create Database access objects
871 int defaultDatabaseIndex = mProxyConfig->getConfigInt("DefaultDatabase", -1);
872 if(defaultDatabaseIndex >= 0)
873 {
874 mAbstractDb = mProxyConfig->getDatabase(defaultDatabaseIndex);
875 if(!mAbstractDb)
876 {
877 CritLog(<<"Failed to get configuration database");
879 return false;
880 }
881 }
882 else // Try legacy configuration parameter names
883 {
884#ifdef USE_MYSQL
885 Data mySQLServer;
886 mProxyConfig->getConfigValue("MySQLServer", mySQLServer);
887 if(!mySQLServer.empty())
888 {
889 WarningLog(<<"Using deprecated parameter MySQLServer, please update to indexed Database definitions.");
890 mAbstractDb = new MySqlDb(*mProxyConfig, mySQLServer,
892 mProxyConfig->getConfigData("MySQLPassword", Data::Empty),
893 mProxyConfig->getConfigData("MySQLDatabaseName", Data::Empty),
894 mProxyConfig->getConfigUnsignedLong("MySQLPort", 0),
895 mProxyConfig->getConfigData("MySQLCustomUserAuthQuery", Data::Empty));
896 }
897#endif
898 if (!mAbstractDb)
899 {
900 mAbstractDb = new BerkeleyDb(mProxyConfig->getConfigData("DatabasePath", "./", true));
901 }
902 }
903 int runtimeDatabaseIndex = mProxyConfig->getConfigInt("RuntimeDatabase", -1);
904 if(runtimeDatabaseIndex >= 0)
905 {
906 mRuntimeAbstractDb = mProxyConfig->getDatabase(runtimeDatabaseIndex);
908 {
909 CritLog(<<"Failed to get runtime database");
911 return false;
912 }
913 }
914#ifdef USE_MYSQL
915 else // Try legacy configuration parameter names
916 {
917 Data runtimeMySQLServer;
918 mProxyConfig->getConfigValue("RuntimeMySQLServer", runtimeMySQLServer);
919 if(!runtimeMySQLServer.empty())
920 {
921 WarningLog(<<"Using deprecated parameter RuntimeMySQLServer, please update to indexed Database definitions.");
922 mRuntimeAbstractDb = new MySqlDb(*mProxyConfig, runtimeMySQLServer,
923 mProxyConfig->getConfigData("RuntimeMySQLUser", Data::Empty),
924 mProxyConfig->getConfigData("RuntimeMySQLPassword", Data::Empty),
925 mProxyConfig->getConfigData("RuntimeMySQLDatabaseName", Data::Empty),
926 mProxyConfig->getConfigUnsignedLong("RuntimeMySQLPort", 0),
927 mProxyConfig->getConfigData("MySQLCustomUserAuthQuery", Data::Empty));
928 }
929 }
930#endif
932 if(!mAbstractDb->isSane())
933 {
934 CritLog(<<"Failed to open configuration database");
936 return false;
937 }
939 {
940 CritLog(<<"Failed to open runtime configuration database");
942 return false;
943 }
945
946 // Create ImMemory Registration Database
947 mRegSyncPort = mProxyConfig->getConfigInt("RegSyncPort", 0);
948 // We only need removed records to linger if we have reg sync enabled
949 if(!mRestarting) // If we are restarting then we left the InMemorySyncRegDb and InMemorySyncPubDb intact at restart - don't recreate
950 {
952 mRegistrationPersistenceManager = new InMemorySyncRegDb(mRegSyncPort ? 86400 /* 24 hours */ : 0 /* removeLingerSecs */); // !slg! could make linger time a setting
954 mPublicationPersistenceManager = new InMemorySyncPubDb((mRegSyncPort && mProxyConfig->getConfigBool("EnablePublicationReplication", false)) ? true : false);
955 }
958
959 // Copy contacts from the StaticRegStore to the RegistrationPersistanceManager
961
962 return true;
963}
964
965void
967{
968 // TODO: let a plugin supply an instance of AuthenticatorFactory
969 // instead of our builtin ReproAuthenticatorFactory
971}
972
973void
975{
976 // Create Profile settings for DUM Instance that handles ServerRegistration,
977 // and potentially certificate subscription server
978 auto profile = std::make_shared<MasterProfile>();
979 profile->setRportEnabled(InteropHelper::getRportEnabled());
980 profile->clearSupportedMethods();
981 profile->addSupportedMethod(resip::REGISTER);
982#ifdef USE_SSL
983 profile->addSupportedScheme(Symbols::Sips);
984#endif
986 {
987 profile->addSupportedOptionTag(Token(Symbols::Outbound));
988 }
989 profile->addSupportedOptionTag(Token(Symbols::Path));
990 if(mProxyConfig->getConfigBool("AllowBadReg", false))
991 {
992 profile->allowBadRegistrationEnabled() = true;
993 }
994#ifdef PACKAGE_VERSION
995 Data serverText(mProxyConfig->getConfigData("ServerText", "repro " PACKAGE_VERSION));
996#else
997 Data serverText(mProxyConfig->getConfigData("ServerText", Data::Empty));
998#endif
999 if(!serverText.empty())
1000 {
1001 profile->setUserAgent(serverText);
1002 }
1003
1004 // Create DialogeUsageManager if Registrar or Certificate Server are enabled
1008 mRegistrar = new Registrar;
1010 bool registrarEnabled = !mProxyConfig->getConfigBool("DisableRegistrar", false);
1011 bool certServerEnabled = mProxyConfig->getConfigBool("EnableCertServer", false);
1012 bool presenceEnabled = mProxyConfig->getConfigBool("EnablePresenceServer", false);
1013 if (registrarEnabled || certServerEnabled || presenceEnabled)
1014 {
1016 mDum->setMasterProfile(profile);
1017 addDomains(*mDum);
1018 }
1019
1020 // If registrar is enabled, configure DUM to handle REGISTER requests
1021 if (registrarEnabled)
1022 {
1027
1028 // Install rules so that the registrar only gets REGISTERs
1030 methodList.push_back(resip::REGISTER);
1033 methodList) );
1034 }
1035
1036 // If Certificate Server is enabled, configure DUM to handle SUBSCRIBE and
1037 // PUBLISH requests for events: credential and certificate
1039 if (certServerEnabled)
1040 {
1041#if defined(USE_SSL)
1042 mCertServer = new CertServer(*mDum);
1043
1044 // Install rules so that the cert server receives SUBSCRIBEs and PUBLISHs
1047 methodList.push_back(resip::SUBSCRIBE);
1048 methodList.push_back(resip::PUBLISH);
1049 eventList.push_back(resip::Symbols::Credential);
1050 eventList.push_back(resip::Symbols::Certificate);
1053 methodList,
1054 eventList));
1055#endif
1056 }
1057
1058 if (presenceEnabled)
1059 {
1062
1063 // Set the publication persistence manager in dum
1065
1066 // Configure DUM to handle SUBSCRIBE and PUBLISH requests for presence
1068 mProxyConfig->getConfigBool("PresenceUsesRegistrationState", true),
1069 mProxyConfig->getConfigBool("PresenceNotifyClosedStateForNonPublishedUsers", true));
1070
1071 // Install rules so that the cert server receives SUBSCRIBEs and PUBLISHs
1074 methodList.push_back(SUBSCRIBE);
1075 methodList.push_back(PUBLISH);
1076 eventList.push_back(Symbols::Presence);
1079 methodList,
1080 eventList));
1081 }
1082
1083 if (mDum)
1084 {
1087
1089 {
1090 // TODO: perhaps this should be initialised from the trusted node
1091 // monkey? Or should the list of trusted TLS peers be independent
1092 // from the trusted node list?
1094 }
1095
1096 Data wsCookieAuthSharedSecret = mProxyConfig->getConfigData("WSCookieAuthSharedSecret", Data::Empty);
1097 if(!mAuthFactory->digestAuthEnabled() && !wsCookieAuthSharedSecret.empty())
1098 {
1099 auto cookieAuth = std::make_shared<WsCookieAuthManager>(*mDum, mDum->dumIncomingTarget());
1100 mDum->addIncomingFeature(cookieAuth);
1101 }
1102
1103 // If Authentication is enabled, then configure DUM to authenticate requests
1105 {
1107 }
1108
1109 // Set the MessageFilterRuleList on DUM and create a thread to run DUM in
1110 mDum->setMessageFilterRuleList(ruleList);
1111 mDumThread = new DumThread(*mDum);
1112 }
1113}
1114
1115bool
1117{
1118 // Create AsyncProcessorDispatcher thread pool that is shared by the processsors for
1119 // any asynchronous tasks (ie: RequestFilter and MessageSilo processors)
1120 int numAsyncProcessorWorkerThreads = mProxyConfig->getConfigInt("NumAsyncProcessorWorkerThreads", 2);
1121 if(numAsyncProcessorWorkerThreads > 0)
1122 {
1124 mAsyncProcessorDispatcher = new Dispatcher(std::unique_ptr<Worker>(new AsyncProcessorWorker),
1125 mSipStack,
1126 numAsyncProcessorWorkerThreads);
1127 }
1128
1129 // Create proxy processor chains
1130 /* Explanation: "Monkeys" are processors which operate on incoming requests
1131 "Lemurs" are processors which operate on incoming responses
1132 "Baboons" are processors which operate on a request for each target
1133 as the request is about to be forwarded to that target */
1134 // Make Monkeys
1138 InfoLog(<< *mMonkeys);
1139#ifdef DSO_PLUGINS
1140 if(mPluginManager)
1141 {
1142 mPluginManager->onRequestProcessorChainPopulated(*mMonkeys);
1143 }
1144#endif
1145
1146 // Make Lemurs
1150 InfoLog(<< *mLemurs);
1151#ifdef DSO_PLUGINS
1152 if(mPluginManager)
1153 {
1154 mPluginManager->onResponseProcessorChainPopulated(*mLemurs);
1155 }
1156#endif
1157
1158 // Make Baboons
1162 InfoLog(<< *mBaboons);
1163#ifdef DSO_PLUGINS
1164 if(mPluginManager)
1165 {
1166 mPluginManager->onTargetProcessorChainPopulated(*mBaboons);
1167 }
1168#endif
1169
1170 // Create main Proxy class
1172 mProxy = new Proxy(*mSipStack,
1173 *mProxyConfig,
1174 *mMonkeys,
1175 *mLemurs,
1176 *mBaboons);
1178 mHttpRealm = mProxyConfig->getConfigData("HttpAdminRealm", mDefaultRealm);
1179
1180 // Set Server Text
1181#ifdef PACKAGE_VERSION
1182 Data serverText(mProxyConfig->getConfigData("ServerText", "repro " PACKAGE_VERSION));
1183#else
1184 Data serverText(mProxyConfig->getConfigData("ServerText", Data::Empty));
1185#endif
1186 if(!serverText.empty())
1187 {
1188 mProxy->setServerText(serverText);
1189 }
1190
1191 // Register the Proxy class a stack transaction user
1192 // Note: This is done after creating the DialogUsageManager so that it acts
1193 // like a catchall and will handle all requests the DUM does not
1195
1196 // Map the Registrar to the Proxy
1197 if(mRegistrar)
1198 {
1200 }
1201
1202 // Add the transport specific RecordRoutes that were stored in addTransports to the Proxy
1203 for(TransportRecordRouteMap::iterator it = mStartupTransportRecordRoutes.begin();
1204 it != mStartupTransportRecordRoutes.end(); it++)
1205 {
1206 mProxy->addTransportRecordRoute(it->first, it->second);
1207 }
1208
1209 return true;
1210}
1211
1212void
1214{
1218
1219 // Copy contacts from the StaticRegStore to the RegistrationPersistanceManager
1221 StaticRegStore::StaticRegRecordMap::iterator it = staticRegList.begin();
1222 for(; it != staticRegList.end(); it++)
1223 {
1224 try
1225 {
1226 Uri aor(it->second.mAor);
1227
1229 rec.mContact = NameAddr(it->second.mContact);
1230 rec.mSipPath = NameAddrs(it->second.mPath);
1232 rec.mSyncContact = true; // Tag this permanent contact as being a synchronized contact so that it will
1233 // not be synchronized to a paired server (this is actually configuration information)
1235 }
1236 catch(resip::ParseBuffer::Exception& e)
1237 {
1238 // This should never happen, since the format should be verified before writing to DB
1239 ErrLog(<<"Failed to apply a static registration due to parse error: " << e);
1240 }
1241 }
1242}
1243
1244bool
1246{
1247 resip_assert(mWebAdminList.empty());
1249
1250 std::vector<resip::Data> httpServerBindAddresses;
1251 mProxyConfig->getConfigValue("HttpBindAddress", httpServerBindAddresses);
1252 int httpPort = mProxyConfig->getConfigInt("HttpPort", 5080);
1253
1254 if(httpPort)
1255 {
1256 if(httpServerBindAddresses.empty())
1257 {
1258 if(mUseV4)
1259 {
1260 httpServerBindAddresses.push_back("0.0.0.0");
1261 }
1262 if(mUseV6)
1263 {
1264 httpServerBindAddresses.push_back("::");
1265 }
1266 }
1267
1268 for(std::vector<resip::Data>::iterator it = httpServerBindAddresses.begin(); it != httpServerBindAddresses.end(); it++)
1269 {
1270 if(mUseV4 && DnsUtil::isIpV4Address(*it))
1271 {
1272 WebAdmin* webAdminV4 = 0;
1273
1274 try
1275 {
1276 webAdminV4 = new WebAdmin(*mProxy,
1279 mHttpRealm,
1280 httpPort,
1281 V4,
1282 *it);
1283 }
1284 catch(WebAdmin::ConfigException& ex)
1285 {
1286 ErrLog(<<"Exception when starting WebAdmin: " << ex.getMessage());
1287 webAdminV4 = 0;
1288 }
1289
1290 if (!webAdminV4 || !webAdminV4->isSane())
1291 {
1292 CritLog(<<"Failed to start WebAdminV4");
1293 delete webAdminV4;
1295 return false;
1296 }
1297
1298 mWebAdminList.push_back(webAdminV4);
1299 }
1300
1301 if(mUseV6 && DnsUtil::isIpV6Address(*it))
1302 {
1303 WebAdmin* webAdminV6 = 0;
1304
1305 try
1306 {
1307 webAdminV6 = new WebAdmin(*mProxy,
1310 mHttpRealm,
1311 httpPort,
1312 V6,
1313 *it);
1314 }
1315 catch(WebAdmin::ConfigException& ex)
1316 {
1317 ErrLog(<<"Exception when starting WebAdmin: " << ex.getMessage());
1318 webAdminV6 = 0;
1319 }
1320
1321 if (!webAdminV6 || !webAdminV6->isSane())
1322 {
1323 CritLog(<<"Failed to start WebAdminV6");
1324 delete webAdminV6;
1326 return false;
1327 }
1328
1329 mWebAdminList.push_back(webAdminV6);
1330 }
1331 }
1332
1333 // This shouldn't happen because it would return false before
1334 // it reached this point
1335 if(!mWebAdminList.empty())
1336 {
1338 return true;
1339 }
1340 }
1341
1342 CritLog(<<"Failed to start any WebAdmin");
1343 return false;
1344}
1345
1346void
1348{
1354 bool enablePublicationReplication = mProxyConfig->getConfigBool("EnablePublicationReplication", false);
1355 std::list<RegSyncServer*> regSyncServerList;
1356 Data regSyncBrokerTopic = mProxyConfig->getConfigData("RegSyncBrokerTopic", Data::Empty);
1357 if(!regSyncBrokerTopic.empty())
1358 {
1359#ifdef BUILD_QPID_PROTON
1361 regSyncBrokerTopic,
1362 enablePublicationReplication ? dynamic_cast<InMemorySyncPubDb*>(mPublicationPersistenceManager) : 0);
1363 regSyncServerList.push_back(mRegSyncServerAMQP);
1364#endif
1365 }
1366 if(mRegSyncPort != 0 || regSyncServerList.size() > 0)
1367 {
1368 if(mUseV4)
1369 {
1371 mRegSyncPort, V4,
1372 enablePublicationReplication ? dynamic_cast<InMemorySyncPubDb*>(mPublicationPersistenceManager) : 0);
1373 regSyncServerList.push_back(mRegSyncServerV4);
1374 }
1375 if(mUseV6)
1376 {
1379 enablePublicationReplication ? dynamic_cast<InMemorySyncPubDb*>(mPublicationPersistenceManager) : 0);
1380 regSyncServerList.push_back(mRegSyncServerV6);
1381 }
1382 if(!regSyncServerList.empty())
1383 {
1384 mRegSyncServerThread = new RegSyncServerThread(regSyncServerList);
1385 }
1386 Data regSyncPeerAddress(mProxyConfig->getConfigData("RegSyncPeer", ""));
1387 if(!regSyncPeerAddress.empty())
1388 {
1389 int remoteRegSyncPort = mProxyConfig->getConfigInt("RemoteRegSyncPort", 0);
1390 if (remoteRegSyncPort == 0)
1391 {
1392 remoteRegSyncPort = mRegSyncPort;
1393 }
1394 if(remoteRegSyncPort != 0)
1395 {
1397 regSyncPeerAddress, remoteRegSyncPort,
1398 enablePublicationReplication ? dynamic_cast<InMemorySyncPubDb*>(mPublicationPersistenceManager) : 0);
1399 }
1400 }
1401 }
1402}
1403
1404void
1406{
1409
1410 std::vector<resip::Data> commandServerBindAddresses;
1411 mProxyConfig->getConfigValue("CommandBindAddress", commandServerBindAddresses);
1412 int commandPort = mProxyConfig->getConfigInt("CommandPort", 5081);
1413
1414 WebAdmin* webAdmin = 0;
1415 if(!mWebAdminList.empty())
1416 {
1417 webAdmin = mWebAdminList.front();
1418 }
1419
1420 if(commandPort != 0)
1421 {
1422 if(commandServerBindAddresses.empty())
1423 {
1424 if(mUseV4)
1425 {
1426 commandServerBindAddresses.push_back("0.0.0.0");
1427 }
1428 if(mUseV6)
1429 {
1430 commandServerBindAddresses.push_back("::");
1431 }
1432 }
1433
1434 for(std::vector<resip::Data>::iterator it = commandServerBindAddresses.begin(); it != commandServerBindAddresses.end(); it++)
1435 {
1436 if(mUseV4 && DnsUtil::isIpV4Address(*it))
1437 {
1438 CommandServer* pCommandServerV4 = new CommandServer(*this, *it, commandPort, V4, webAdmin);
1439
1440 if(pCommandServerV4->isSane())
1441 {
1442 mCommandServerList.push_back(pCommandServerV4);
1443 }
1444 else
1445 {
1446 CritLog(<<"Failed to start CommandServerV4");
1447 delete pCommandServerV4;
1448 }
1449 }
1450
1451 if(mUseV6 && DnsUtil::isIpV6Address(*it))
1452 {
1453 CommandServer* pCommandServerV6 = new CommandServer(*this, *it, commandPort, V6, webAdmin);
1454
1455 if(pCommandServerV6->isSane())
1456 {
1457 mCommandServerList.push_back(pCommandServerV6);
1458 }
1459 else
1460 {
1461 CritLog(<<"Failed to start CommandServerV6");
1462 delete pCommandServerV6;
1463 }
1464 }
1465 }
1466 }
1467
1468#ifdef BUILD_QPID_PROTON
1469 std::vector<resip::Data> commandServerQueues;
1470 mProxyConfig->getConfigValue("CommandQueue", commandServerQueues);
1471 for(Data& brokerUrl : commandServerQueues)
1472 {
1473 CommandServer* pCommandServerQueue = new CommandServer(*this, brokerUrl, false, webAdmin);
1474 if(pCommandServerQueue->isSane())
1475 {
1476 mCommandServerList.push_back(pCommandServerQueue);
1477 }
1478 else
1479 {
1480 CritLog(<<"Failed to start CommandServerQueue");
1481 delete pCommandServerQueue;
1482 }
1483 }
1484
1485 std::vector<resip::Data> commandServerTopics;
1486 mProxyConfig->getConfigValue("CommandEventTopic", commandServerTopics);
1487 for(Data& brokerUrl : commandServerTopics)
1488 {
1489 CommandServer* pCommandServerTopic = new CommandServer(*this, brokerUrl, true, webAdmin);
1490 if(pCommandServerTopic->isSane())
1491 {
1492 mCommandServerList.push_back(pCommandServerTopic);
1493 }
1494 else
1495 {
1496 CritLog(<<"Failed to start CommandServerTopic");
1497 delete pCommandServerTopic;
1498 }
1499 }
1500#endif
1501
1502 if(!mCommandServerList.empty())
1503 {
1505 }
1506}
1507
1508void
1510{
1512
1513 auto matcher = std::make_shared<ExtendedDomainMatcher>();
1514 mDomainMatcher = matcher;
1515
1516 std::vector<Data> configDomains;
1517 if(mProxyConfig->getConfigValue("Domains", configDomains))
1518 {
1519 for (std::vector<Data>::const_iterator i=configDomains.begin();
1520 i != configDomains.end(); ++i)
1521 {
1522 InfoLog (<< "Adding domain " << *i << " from command line");
1523 matcher->addDomain(*i);
1524 if ( mDefaultRealm.empty() )
1525 {
1526 mDefaultRealm = *i;
1527 }
1528 }
1529 }
1530
1531 std::vector<Data> configDomainSuffixes;
1532 if(mProxyConfig->getConfigValue("DomainSuffixes", configDomainSuffixes))
1533 {
1534 for (std::vector<Data>::const_iterator i=configDomainSuffixes.begin();
1535 i != configDomainSuffixes.end(); ++i)
1536 {
1537 InfoLog (<< "Adding domain suffix " << *i << " from command line");
1538 matcher->addDomainSuffix(*i);
1539 if ( mDefaultRealm.empty() )
1540 {
1541 mDefaultRealm = *i;
1542 }
1543 }
1544 }
1545
1547 for (ConfigStore::ConfigData::const_iterator i=dList.begin();
1548 i != dList.end(); ++i)
1549 {
1550 InfoLog (<< "Adding domain " << i->second.mDomain << " from config");
1551 matcher->addDomain( i->second.mDomain );
1552 if ( mDefaultRealm.empty() )
1553 {
1554 mDefaultRealm = i->second.mDomain;
1555 }
1556 }
1557
1558 /* All of this logic has been commented out - the sysadmin must explicitly
1559 add any of the items below to the Domains config option in repro.config
1560
1561 Data localhostname(DnsUtil::getLocalHostName());
1562 InfoLog (<< "Adding local hostname domain " << localhostname );
1563 matcher->addDomain(localhostname);
1564 if ( mDefaultRealm.empty() )
1565 {
1566 mDefaultRealm = localhostname;
1567 }
1568
1569 InfoLog (<< "Adding localhost domain.");
1570 matcher->addDomain("localhost");
1571 if ( mDefaultRealm.empty() )
1572 {
1573 mDefaultRealm = "localhost";
1574 }
1575
1576 list<pair<Data,Data> > ips = DnsUtil::getInterfaces();
1577 for ( list<pair<Data,Data> >::const_iterator i=ips.begin(); i!=ips.end(); i++)
1578 {
1579 InfoLog( << "Adding domain for IP " << i->second << " from interface " << i->first );
1580 matcher->addDomain(i->second);
1581 }
1582
1583 InfoLog (<< "Adding 127.0.0.1 domain.");
1584 matcher->addDomain("127.0.0.1"); */
1585
1586 if( mDefaultRealm.empty() )
1587 {
1588 mDefaultRealm = "Unconfigured";
1589 }
1590}
1591
1592void
1601
1602bool
1603ReproRunner::addTransports(bool& allTransportsSpecifyRecordRoute)
1604{
1607
1608 allTransportsSpecifyRecordRoute=false;
1610
1611 bool useEmailAsSIP = mProxyConfig->getConfigBool("TLSUseEmailAsSIP", false);
1612 Data wsCookieAuthSharedSecret = mProxyConfig->getConfigData("WSCookieAuthSharedSecret", Data::Empty);
1613 std::shared_ptr<BasicWsConnectionValidator> basicWsConnectionValidator;
1614 std::shared_ptr<WsCookieContextFactory> wsCookieContextFactory;
1615 if(!wsCookieAuthSharedSecret.empty())
1616 {
1617 basicWsConnectionValidator = std::make_shared<BasicWsConnectionValidator>(wsCookieAuthSharedSecret);
1618 Data infoCookieName = mProxyConfig->getConfigData("WSCookieNameInfo", Data::Empty);
1619 Data extraCookieName = mProxyConfig->getConfigData("WSCookieNameExtra", Data::Empty);
1620 Data macCookieName = mProxyConfig->getConfigData("WSCookieNameMac", Data::Empty);
1621
1622 wsCookieContextFactory = std::make_shared<BasicWsCookieContextFactory>(infoCookieName, extraCookieName, macCookieName);
1623 }
1624
1625 try
1626 {
1627 // Check if advanced transport settings are provided
1629 DebugLog(<<"Found " << m.size() << " interface(s) defined in the advanced format");
1630 if(!m.empty())
1631 {
1632 // Sample config file format for advanced transport settings
1633 // Transport1Interface = 192.168.1.106:5061
1634 // Transport1Type = TLS
1635 // Transport1TlsDomain = sipdomain.com
1636 // Transport1TlsCertificate = /etc/ssl/crt/sipdomain.com.pem
1637 // Transport1TlsPrivateKey = /etc/ssl/private/sipdomain.com.pem
1638 // Transport1TlsPrivateKeyPassPhrase = <pwd>
1639 // Transport1TlsClientVerification = None
1640 // Transport1RecordRouteUri = sip:sipdomain.com;transport=TLS
1641 // Transport1RcvBufLen = 2000
1642
1643 allTransportsSpecifyRecordRoute = true;
1644
1645 const char *anchor;
1646 for(ConfigParse::NestedConfigMap::iterator it = m.begin();
1647 it != m.end();
1648 it++)
1649 {
1650 int idx = it->first;
1651 SipConfigParse tc(it->second);
1652 Data transportPrefix = "Transport" + Data(idx);
1653 DebugLog(<< "checking values for transport: " << idx);
1654 Data interfaceSettings = tc.getConfigData("Interface", Data::Empty, true);
1655
1656 // Parse out interface settings
1657 ParseBuffer pb(interfaceSettings);
1658 anchor = pb.position();
1659 pb.skipToEnd();
1660 pb.skipBackToChar(':'); // For IPv6 the last : should be the port
1661 pb.skipBackChar();
1662 if(!pb.eof())
1663 {
1664 Data ipAddr;
1665 Data portData;
1666 pb.data(ipAddr, anchor);
1667 pb.skipChar();
1668 anchor = pb.position();
1669 pb.skipToEnd();
1670 pb.data(portData, anchor);
1671 if(!DnsUtil::isIpAddress(ipAddr))
1672 {
1673 CritLog(<< "Malformed IP-address found in " << transportPrefix << "Interface setting: " << ipAddr);
1674 }
1675 int port = portData.convertInt();
1676 if(port == 0)
1677 {
1678 CritLog(<< "Invalid port found in " << transportPrefix << " setting: " << port);
1679 }
1680 TransportType tt = Tuple::toTransport(tc.getConfigData("Type", "UDP"));
1681 if(tt == UNKNOWN_TRANSPORT)
1682 {
1683 CritLog(<< "Unknown transport type found in " << transportPrefix << "Type setting: " << tc.getConfigData("Type", "UDP"));
1684 }
1685 Data tlsDomain = tc.getConfigData("TlsDomain", Data::Empty);
1686 Data tlsCertificate = tc.getConfigData("TlsCertificate", Data::Empty);
1687 Data tlsPrivateKey = tc.getConfigData("TlsPrivateKey", Data::Empty);
1688 Data tlsPrivateKeyPassPhrase = tc.getConfigData("TlsPrivateKeyPassPhrase", Data::Empty);
1691#ifdef USE_SSL
1692 sslType = tc.getConfigSSLType("TlsConnectionMethod", DEFAULT_TLS_METHOD);
1693#endif
1694
1695#ifdef USE_SSL
1696 // Make sure certificate material available before trying to instantiate Transport
1697 if(isSecure(tt))
1698 {
1699 Security* security = mSipStack->getSecurity();
1700 resip_assert(security != 0);
1701 // FIXME: see comments about CertificatePath
1702 if(!tlsCertificate.empty())
1703 {
1704 security->addDomainCertPEM(tlsDomain, Data::fromFile(tlsCertificate));
1705 }
1706 if(!tlsPrivateKey.empty())
1707 {
1708 security->addDomainPrivateKeyPEM(tlsDomain, Data::fromFile(tlsPrivateKey), tlsPrivateKeyPassPhrase);
1709 }
1710 }
1711#endif
1712
1714 port,
1715 DnsUtil::isIpV6Address(ipAddr) ? V6 : V4,
1716 StunEnabled,
1717 ipAddr, // interface to bind to
1718 tlsDomain,
1719 tlsPrivateKeyPassPhrase, // private key passphrase
1720 sslType, // sslType
1721 0, // transport flags
1722 tlsCertificate, tlsPrivateKey,
1723 cvm, // tls client verification mode
1724 useEmailAsSIP,
1725 basicWsConnectionValidator, wsCookieContextFactory);
1726
1727 if (t)
1728 {
1729 int rcvBufLen = tc.getConfigInt("RcvBufLen", 0);
1730 if (rcvBufLen >0 )
1731 {
1732#if defined(RESIP_SIPSTACK_HAVE_FDPOLL)
1733 // this new method is part of the epoll changeset,
1734 // which isn't commited yet.
1735 t->setRcvBufLen(rcvBufLen);
1736#else
1737 resip_assert(0);
1738#endif
1739 }
1740
1741 Data recordRouteUri = tc.getConfigData("RecordRouteUri", Data::Empty);
1742 if(!recordRouteUri.empty())
1743 {
1744 try
1745 {
1746 if(isEqualNoCase(recordRouteUri, "auto")) // auto generated record route uri
1747 {
1748 NameAddr rr;
1749 if(isSecure(tt))
1750 {
1751 rr.uri().host()=tlsDomain;
1752 }
1753 else
1754 {
1755 rr.uri().host()=ipAddr;
1756 }
1757 rr.uri().port()=port;
1758 rr.uri().param(resip::p_transport)=resip::Tuple::toDataLower(tt);
1759 mStartupTransportRecordRoutes[t->getKey()] = rr; // Store to be added to Proxy after it is created
1760 InfoLog (<< "Transport specific record-route enabled (generated): " << rr);
1761 }
1762 else
1763 {
1764 NameAddr rr(recordRouteUri);
1765 mStartupTransportRecordRoutes[t->getKey()] = rr; // Store to be added to Proxy after it is created
1766 InfoLog (<< "Transport specific record-route enabled: " << rr);
1767 }
1768 }
1769 catch(BaseException& e)
1770 {
1771 ErrLog (<< "Invalid uri provided in " << transportPrefix << "RecordRouteUri setting (ignoring): " << e);
1772 allTransportsSpecifyRecordRoute = false;
1773 }
1774 }
1775 else
1776 {
1777 allTransportsSpecifyRecordRoute = false;
1778 }
1779 }
1780 }
1781 else
1782 {
1783 CritLog(<< "Port not specified in " << transportPrefix << " setting: expected format is <IPAddress>:<Port>");
1784 return false;
1785 }
1786 }
1787 }
1788 else
1789 {
1790 Data ipAddress = mProxyConfig->getConfigData("IPAddress", Data::Empty, true);
1791 bool isV4Address = DnsUtil::isIpV4Address(ipAddress);
1792 bool isV6Address = DnsUtil::isIpV6Address(ipAddress);
1793 if(!isV4Address && !isV6Address)
1794 {
1795 if (!ipAddress.empty())
1796 {
1797 ErrLog(<< "Malformed IP-address found in IPAddress setting, ignoring (binding to all interfaces): " << ipAddress);
1798 }
1799 ipAddress = Data::Empty;
1800 isV4Address = true;
1801 isV6Address = true;
1802 }
1803 int udpPort = mProxyConfig->getConfigInt("UDPPort", 5060);
1804 int tcpPort = mProxyConfig->getConfigInt("TCPPort", 5060);
1805 int tlsPort = mProxyConfig->getConfigInt("TLSPort", 5061);
1806 int wsPort = mProxyConfig->getConfigInt("WSPort", 80);
1807 int wssPort = mProxyConfig->getConfigInt("WSSPort", 443);
1808 int dtlsPort = mProxyConfig->getConfigInt("DTLSPort", 0);
1809 Data tlsDomain = mProxyConfig->getConfigData("TLSDomainName", Data::Empty);
1810 Data tlsCertificate = mProxyConfig->getConfigData("TLSCertificate", Data::Empty);
1811 Data tlsPrivateKey = mProxyConfig->getConfigData("TLSPrivateKey", Data::Empty);
1812 Data tlsPrivateKeyPassPhrase = mProxyConfig->getConfigData("TlsPrivateKeyPassPhrase", Data::Empty);
1815#ifdef USE_SSL
1816 sslType = mProxyConfig->getConfigSSLType("TLSConnectionMethod", DEFAULT_TLS_METHOD);
1817#endif
1818
1819#ifdef USE_SSL
1820 // Make sure certificate material available before trying to instantiate Transport
1821 if (tlsPort || wssPort || dtlsPort)
1822 {
1823 Security* security = mSipStack->getSecurity();
1824 resip_assert(security != 0);
1825 // FIXME: should check that EITHER CertificatePath was set or both of these
1826 // are supplied
1827 // In any case, it will still give a helpful error when it fails to
1828 // create the transport
1829 if(!tlsCertificate.empty())
1830 {
1831 security->addDomainCertPEM(tlsDomain, Data::fromFile(tlsCertificate));
1832 }
1833 if(!tlsPrivateKey.empty())
1834 {
1835 security->addDomainPrivateKeyPEM(tlsDomain, Data::fromFile(tlsPrivateKey));
1836 }
1837 }
1838#endif
1839
1840 if (udpPort)
1841 {
1842 if (mUseV4 && isV4Address) mSipStack->addTransport(UDP, udpPort, V4, StunEnabled, ipAddress);
1843 if (mUseV6 && isV6Address) mSipStack->addTransport(UDP, udpPort, V6, StunEnabled, ipAddress);
1844 }
1845 if (tcpPort)
1846 {
1847 if (mUseV4 && isV4Address) mSipStack->addTransport(TCP, tcpPort, V4, StunEnabled, ipAddress);
1848 if (mUseV6 && isV6Address) mSipStack->addTransport(TCP, tcpPort, V6, StunEnabled, ipAddress);
1849 }
1850 if (tlsPort)
1851 {
1852 if (mUseV4 && isV4Address) mSipStack->addTransport(TLS, tlsPort, V4, StunEnabled, ipAddress, tlsDomain, tlsPrivateKeyPassPhrase, sslType, 0, tlsCertificate, tlsPrivateKey, cvm, useEmailAsSIP);
1853 if (mUseV6 && isV6Address) mSipStack->addTransport(TLS, tlsPort, V6, StunEnabled, ipAddress, tlsDomain, tlsPrivateKeyPassPhrase, sslType, 0, tlsCertificate, tlsPrivateKey, cvm, useEmailAsSIP);
1854 }
1855 if (wsPort)
1856 {
1857 if (mUseV4 && isV4Address) mSipStack->addTransport(WS, wsPort, V4, StunEnabled, ipAddress, Data::Empty, Data::Empty, SecurityTypes::NoSSL, 0, Data::Empty, Data::Empty, SecurityTypes::None, false, basicWsConnectionValidator, wsCookieContextFactory);
1858 if (mUseV6 && isV6Address) mSipStack->addTransport(WS, wsPort, V6, StunEnabled, ipAddress, Data::Empty, Data::Empty, SecurityTypes::NoSSL, 0, Data::Empty, Data::Empty, SecurityTypes::None, false, basicWsConnectionValidator, wsCookieContextFactory);
1859 }
1860 if (wssPort)
1861 {
1862 if (mUseV4 && isV4Address) mSipStack->addTransport(WSS, wssPort, V4, StunEnabled, ipAddress, tlsDomain, tlsPrivateKeyPassPhrase, sslType, 0, tlsCertificate, tlsPrivateKey, cvm, useEmailAsSIP, basicWsConnectionValidator, wsCookieContextFactory);
1863 if (mUseV6 && isV6Address) mSipStack->addTransport(WSS, wssPort, V6, StunEnabled, ipAddress, tlsDomain, tlsPrivateKeyPassPhrase, sslType, 0, tlsCertificate, tlsPrivateKey, cvm, useEmailAsSIP, basicWsConnectionValidator, wsCookieContextFactory);
1864 }
1865 if (dtlsPort)
1866 {
1867 if (mUseV4 && isV4Address) mSipStack->addTransport(DTLS, dtlsPort, V4, StunEnabled, ipAddress, tlsDomain, tlsPrivateKeyPassPhrase, sslType, 0, tlsCertificate, tlsPrivateKey);
1868 if (mUseV6 && isV6Address) mSipStack->addTransport(DTLS, dtlsPort, V6, StunEnabled, ipAddress, tlsDomain, tlsPrivateKeyPassPhrase, sslType, 0, tlsCertificate, tlsPrivateKey);
1869 }
1870 }
1871 }
1872 catch (BaseException& e)
1873 {
1874 std::cerr << "Likely a port is already in use" << endl;
1875 InfoLog (<< "Caught: " << e);
1876 return false;
1877 }
1878 return true;
1879}
1880
1881void
1882ReproRunner::addProcessor(repro::ProcessorChain& chain, std::unique_ptr<Processor> processor)
1883{
1884 chain.addProcessor(std::move(processor));
1885}
1886
1887void // Monkeys
1889{
1892
1893 // Add strict route fixup monkey
1894 addProcessor(chain, std::unique_ptr<Processor>(new StrictRouteFixup));
1895
1896 // Add is trusted node monkey
1897 addProcessor(chain, std::unique_ptr<Processor>(new IsTrustedNode(*mProxyConfig)));
1898
1899 // Add Certificate Authenticator - if required
1902 {
1903 // TODO: perhaps this should be initialised from the trusted node
1904 // monkey? Or should the list of trusted TLS peers be independent
1905 // from the trusted node list?
1906 // Should we used the same trustedPeers object that was
1907 // passed to TlsPeerAuthManager perhaps?
1909 }
1910
1911 Data wsCookieAuthSharedSecret = mProxyConfig->getConfigData("WSCookieAuthSharedSecret", Data::Empty);
1912 Data wsCookieExtraHeaderName = mProxyConfig->getConfigData("WSCookieExtraHeaderName", "X-WS-Session-Extra");
1913 if(!mAuthFactory->digestAuthEnabled() && !wsCookieAuthSharedSecret.empty())
1914 {
1915 addProcessor(chain, std::unique_ptr<Processor>(new CookieAuthenticator(wsCookieAuthSharedSecret, wsCookieExtraHeaderName, mSipStack)));
1916 }
1917
1918 // Add digest authenticator monkey - if required
1920 {
1922 }
1923
1924 // Add am I responsible monkey
1925 addProcessor(chain, std::unique_ptr<Processor>(new AmIResponsible(mProxyConfig->getConfigBool("AlwaysAllowRelaying", false))));
1926
1927 // Add RequestFilter monkey
1928 if(!mProxyConfig->getConfigBool("DisableRequestFilterProcessor", false))
1929 {
1931 {
1932 addProcessor(chain, std::unique_ptr<Processor>(new RequestFilter(*mProxyConfig, mAsyncProcessorDispatcher)));
1933 }
1934 else
1935 {
1936 WarningLog(<< "Could not start RequestFilter Processor due to no worker thread pool (NumAsyncProcessorWorkerThreads=0)");
1937 }
1938 }
1939
1940 // [TODO] support for GRUU is on roadmap. When it is added the GruuMonkey will go here
1941
1942 // [TODO] support for Manipulating Tel URIs is on the roadmap.
1943 // When added, the telUriMonkey will go here
1944
1945 std::vector<Data> routeSet;
1946 mProxyConfig->getConfigValue("Routes", routeSet);
1947 if (routeSet.empty())
1948 {
1949 // add static route monkey
1950 addProcessor(chain, std::unique_ptr<Processor>(new StaticRoute(*mProxyConfig)));
1951 }
1952 else
1953 {
1954 // add simple static route monkey
1955 addProcessor(chain, std::unique_ptr<Processor>(new SimpleStaticRoute(*mProxyConfig)));
1956 }
1957
1958 // Add location server monkey
1960
1961 // Add message silo monkey
1962 if(mProxyConfig->getConfigBool("MessageSiloEnabled", false))
1963 {
1965 {
1968 addProcessor(chain, std::unique_ptr<Processor>(silo));
1969 }
1970 else
1971 {
1972 WarningLog(<< "Could not start MessageSilo Processor due to no worker thread pool (NumAsyncProcessorWorkerThreads=0) or Registrar");
1973 }
1974 }
1975}
1976
1977void // Lemurs
1979{
1982
1983 // Add outbound target handler lemur
1984 addProcessor(chain, std::unique_ptr<Processor>(new OutboundTargetHandler(*mRegistrationPersistenceManager)));
1985
1986 if (mProxyConfig->getConfigBool("RecursiveRedirect", false))
1987 {
1988 // Add recursive redirect lemur
1989 addProcessor(chain, std::unique_ptr<Processor>(new RecursiveRedirect));
1990 }
1991}
1992
1993void // Baboons
1995{
1997
1998#ifndef RESIP_FIXED_POINT
1999 if(mProxyConfig->getConfigBool("GeoProximityTargetSorting", false))
2000 {
2001 addProcessor(chain, std::unique_ptr<Processor>(new GeoProximityTargetSorter(*mProxyConfig)));
2002 }
2003#endif
2004
2005 if(mProxyConfig->getConfigBool("QValue", true))
2006 {
2007 // Add q value target handler baboon
2008 addProcessor(chain, std::unique_ptr<Processor>(new QValueTargetHandler(*mProxyConfig)));
2009 }
2010
2011 // Add simple target handler baboon
2012 addProcessor(chain, std::unique_ptr<Processor>(new SimpleTargetHandler));
2013}
2014
2015bool
2017{
2018 // Dispatch to each command server
2019 for(std::list<CommandServer*>::iterator it = mCommandServerList.begin(); it != mCommandServerList.end(); it++)
2020 {
2021 (*it)->handleStatisticsMessage(statsMessage);
2022 }
2023 // Dispatch to each web admin (so REST /api/v1/stats callers can receive
2024 // the payload).
2025 for(std::list<WebAdmin*>::iterator it = mWebAdminList.begin(); it != mWebAdminList.end(); it++)
2026 {
2027 (*it)->handleStatisticsMessage(statsMessage);
2028 }
2029 return true;
2030}
2031
2032/* ====================================================================
2033 * The Vovida Software License, Version 1.0
2034 *
2035 * Copyright (c) 2026, SIP Spectrum, Inc. https://www.sipspectrum.com
2036 * Copyright (c) 2022, Software Freedom Institute https://softwarefreedom.institute
2037 * Copyright (c) 2022, Daniel Pocock https://danielpocock.com
2038 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
2039 *
2040 * Redistribution and use in source and binary forms, with or without
2041 * modification, are permitted provided that the following conditions
2042 * are met:
2043 *
2044 * 1. Redistributions of source code must retain the above copyright
2045 * notice, this list of conditions and the following disclaimer.
2046 *
2047 * 2. Redistributions in binary form must reproduce the above copyright
2048 * notice, this list of conditions and the following disclaimer in
2049 * the documentation and/or other materials provided with the
2050 * distribution.
2051 *
2052 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
2053 * and "Vovida Open Communication Application Library (VOCAL)" must
2054 * not be used to endorse or promote products derived from this
2055 * software without prior written permission. For written
2056 * permission, please contact vocal@vovida.org.
2057 *
2058 * 4. Products derived from this software may not be called "VOCAL", nor
2059 * may "VOCAL" appear in their name, without prior written
2060 * permission of Vovida Networks, Inc.
2061 *
2062 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
2063 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2064 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
2065 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
2066 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
2067 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
2068 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2069 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2070 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
2071 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2072 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
2073 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
2074 * DAMAGE.
2075 *
2076 * ====================================================================
2077 */
ParserContainer< NameAddr > NameAddrs
Definition Headers.cxx:195
#define DebugLog(args_)
Definition Logger.hxx:128
#define InfoLog(args_)
Definition Logger.hxx:131
#define CritLog(args_)
Definition Logger.hxx:140
#define WarningLog(args_)
Definition Logger.hxx:134
#define ErrLog(args_)
Definition Logger.hxx:137
#define DEFAULT_TLS_METHOD
ReproLogger g_ReproLogger
#define resip_assert(x)
This file needs to work for both C and C++ code.
AbstractDb * getDatabase(int configIndex)
virtual ~ReproLogger()
virtual bool operator()(Log::Level level, const Subsystem &subsystem, const Data &appName, const char *file, int line, const Data &message, const Data &messageWithHeaders, const Data &instanceName)
return true to also do default logging, false to supress default logging.
virtual void outboundRetransmit(const Tuple &source, const Tuple &destination, const SendData &data)
virtual void inboundMessage(const Tuple &source, const Tuple &destination, const SipMessage &msg)
virtual void outboundMessage(const Tuple &source, const Tuple &destination, const SipMessage &msg)
virtual bool isSane()=0
virtual std::shared_ptr< resip::DumFeature > getCertificateAuthManager()=0
virtual std::unique_ptr< Processor > getCertificateAuthenticator()=0
virtual std::unique_ptr< Processor > getDigestAuthenticator()=0
virtual resip::Dispatcher * getDispatcher()=0
virtual bool digestAuthEnabled()=0
virtual bool certificateAuthEnabled()=0
virtual void setDum(resip::DialogUsageManager *dum)=0
virtual std::shared_ptr< resip::ServerAuthManager > getServerAuthManager()=0
std::map< resip::Data, AbstractDb::ConfigRecord > ConfigData
const ConfigData & getConfigs() const
void addProcessor(std::unique_ptr< Processor >)
void createDataStore(AbstractDb *db, AbstractDb *runtimedb=0)
virtual AbstractDb * getDatabase(int configIndex)
void setServerText(const resip::Data &text)
Definition Proxy.hxx:102
void addTransportRecordRoute(unsigned int transportKey, const resip::NameAddr &recordRoute)
Definition Proxy.cxx:630
virtual void shutdown()
void setProxy(Proxy *proxy)
Definition Registrar.hxx:46
virtual void addRegistrarHandler(RegistrarHandler *handler)
Definition Registrar.cxx:25
virtual void restart()
virtual void shutdown()
virtual bool run(int argc, char **argv)
virtual void createAuthenticatorFactory()
virtual void createCommandServer()
virtual bool createWebAdmin()
resip::DialogUsageManager * mDum
virtual void setOpenSSLCTXOptionsFromConfig(const resip::Data &configVar, long &opts)
CertServer * mCertServer
std::list< CommandServer * > mCommandServerList
resip::RegistrationPersistenceManager * mRegistrationPersistenceManager
virtual void makeResponseProcessorChain(repro::ProcessorChain &chain)
std::shared_ptr< resip::DomainMatcher > mDomainMatcher
resip::SipStack * mSipStack
CommandServerThread * mCommandServerThread
resip::ThreadIf * mStackThread
virtual void addDomains(resip::TransactionUser &tu)
RegSyncServerThread * mRegSyncServerThread
AbstractDb * mAbstractDb
ProxyConfig * mProxyConfig
virtual void makeTargetProcessorChain(repro::ProcessorChain &chain)
virtual void addProcessor(repro::ProcessorChain &chain, std::unique_ptr< repro::Processor > processor)
std::list< WebAdmin * > mWebAdminList
Registrar * mRegistrar
virtual bool loadPlugins()
PresenceServer * mPresenceServer
AuthenticatorFactory * mAuthFactory
virtual void makeRequestProcessorChain(repro::ProcessorChain &chain)
resip::FdPollGrp * mFdPollGrp
resip::CongestionManager * mCongestionManager
resip::Data mHttpRealm
RegSyncServer * mRegSyncServerV6
resip::ThreadIf * mDumThread
resip::Data mDefaultRealm
virtual void onReload()
RegSyncClient * mRegSyncClient
WebAdminThread * mWebAdminThread
RegSyncServer * mRegSyncServerAMQP
virtual bool createProxy()
resip::PublicationPersistenceManager * mPublicationPersistenceManager
ProcessorChain * mMonkeys
ProcessorChain * mLemurs
resip::Dispatcher * mAsyncProcessorDispatcher
RegSyncServer * mRegSyncServerV4
virtual void initDomainMatcher()
ProcessorChain * mBaboons
virtual void cleanupObjects()
virtual bool addTransports(bool &allTransportsSpecifyRecordRoute)
virtual void populateRegistrations()
virtual void createRegSync()
virtual bool createDatastore()
virtual bool createSipStack()
virtual bool operator()(resip::StatisticsMessage &statsMessage)
TransportRecordRouteMap mStartupTransportRecordRoutes
virtual void createDialogUsageManager()
AbstractDb * mRuntimeAbstractDb
resip::AsyncProcessHandler * mAsyncProcessHandler
StaticRegRecordMap & getStaticRegList()
std::map< std::pair< resip::Uri, resip::Uri >, StaticRegRecord > StaticRegRecordMap
ConfigStore mConfigStore
Definition Store.hxx:38
StaticRegStore mStaticRegStore
Definition Store.hxx:39
static const VersionUtils & instance()
The abstract base-class for all exceptions thrown by resip code.
const Data & getMessage() const noexcept
static long OpenSSLCTXClearOptions
Definition Security.hxx:92
static void setAllowWildcardCertificates(bool bEnable)
Definition Security.hxx:197
void addDomainPrivateKeyPEM(const Data &domainName, const Data &privateKeyPEM, const Data &privateKeyPassPhrase=Data::Empty)
static long OpenSSLCTXSetOptions
Note:
Definition Security.hxx:91
void addDomainCertPEM(const Data &domainName, const Data &certPEM)
virtual void parseConfig(int argc, char **argv, const resip::Data &defaultConfigFilename)
int getConfigInt(const resip::Data &name, int defaultValue) const
NestedConfigMap getConfigNested(const resip::Data &mapsPrefix) const
resip::Data getConfigData(const resip::Data &name, const resip::Data &defaultValue, bool useDefaultIfEmpty=false) const
HashMap< int, NestedConfigParse > NestedConfigMap
unsigned long getConfigUnsignedLong(const resip::Data &name, unsigned long defaultValue) const
bool getConfigBool(const resip::Data &name, bool defaultValue) const
static void setMessageSizeMax(size_t max)
static bool EnableAgressiveGc
Enable Agressive Connection Garbage Collection to have resip perform garbage collection on every new ...
static uint64_t MinimumGcAge
connection must have no inbound traffic for greater than this time (in ms) before it is garbage colle...
static uint64_t MinimumGcHeadroom
If the difference between the number of permitted FDs (reported by periodic calls to getrlimit()) and...
A single contact record, bound to an Aor during registration.
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
static const Data Empty
Constant that represents a zero-length data.
Definition Data.hxx:882
const char * c_str() const
Returns a null-terminated string representing.
Definition Data.cxx:1097
static Data fromFile(const Data &filename)
Definition Data.cxx:2539
bool empty() const noexcept
Checks whether the Data is empty.
Definition Data.hxx:591
Data & lowercase()
Converts this Data to lowercase.
Definition Data.cxx:1635
int convertInt() const
Takes the contents of the Data and converts them to an integer.
Definition Data.cxx:1684
void setServerRegistrationHandler(ServerRegistrationHandler *)
If no such handler, UAS will respond to REGISTER with 405 Method Not Allowed.
void setServerAuthManager(std::shared_ptr< ServerAuthManager > server)
If there is no ServerAuthManager, the server does not authenticate requests.
void setRegistrationPersistenceManager(RegistrationPersistenceManager *)
Sets a manager to handle storage of registration or publication state.
void setMasterProfile(const std::shared_ptr< MasterProfile > &masterProfile)
void addIncomingFeature(std::shared_ptr< DumFeature > feat)
TargetCommand::Target & dumIncomingTarget()
void setPublicationPersistenceManager(PublicationPersistenceManager *)
A generic thread-bank class.
std::vector< GenericIPAddress > NameserverList
Definition DnsStub.hxx:117
static bool isIpV6Address(const Data &ipAddress)
Definition DnsUtil.cxx:386
static bool isIpAddress(const Data &ipAddress)
Definition DnsUtil.cxx:453
static bool isIpV4Address(const Data &ipAddress)
Definition DnsUtil.cxx:290
This class creates a thread in which to run one or more SipStacks.
Interface functor for external logging.
Definition Log.hxx:448
static FdPollGrp * create(const char *implName=NULL)
factory
Definition FdPoll.cxx:972
This is a general-purpose congestion manager.
MetricType
Enumeration of congestion metric types this class supports.
@ WAIT_TIME
The expected service time (the time it takes for new items to be serviced) This is the recommended me...
@ SIZE
The current size of the fifo.
@ TIME_DEPTH
The age of the oldest item in the fifo.
Implementation of a persistence manager.
Implementation of a persistence manager.
static void setAllowInboundFlowTokensForNonDirectClients(bool enabled)
static void setOutboundVersion(int version)
static bool getRRTokenHackEnabled()
static void setRportEnabled(bool enable)
static void setAssumeFirstHopSupportsFlowTokensEnabled(bool enabled)
static void setRRTokenHackEnabled(bool enabled)
static bool getOutboundSupported()
static InteropHelper::ClientNATDetectionMode getClientNATDetectionMode()
static void setClientNATDetectionMode(InteropHelper::ClientNATDetectionMode mode)
static void setFlowTimerSeconds(unsigned int seconds)
static void setOutboundSupported(bool supported)
static bool getRportEnabled()
static void setAssumeFirstHopSupportsOutboundEnabled(bool enabled)
static void initialize(Type type, Level level, const Data &appName, const char *logFileName=0, ExternalLogger *externalLogger=0, const Data &syslogFacility="LOG_DAEMON", MessageStructure messageStructure=Unstructured, const Data &instanceName="")
Definition Log.cxx:268
std::vector< Data > EventList
std::vector< MethodTypes > MethodList
std::vector< Data > SchemeList
Represents the "name-addr" and the "addr-spec" elements in the RFC 3261 grammar.
Definition NameAddr.hxx:19
Provides string-parsing functionality with protection from buffer overflow.
const char * skipBackToChar(char c)
CurrentPosition skipToEnd()
const char * skipBackChar()
CurrentPosition position() const
CurrentPosition skipChar()
void data(Data &data, const char *start) const
make the passed in data share memory with the buffer (uses Data::Share)
virtual update_status_t updateContact(const Uri &aor, const ContactInstanceRecord &rec)=0
void addCADirectory(const Data &caDirectory)
Definition Security.cxx:215
void addCAFile(const Data &caFile)
Definition Security.cxx:226
void dropPrivileges(const Data &runAsUser, const Data &runAsGroup)
void setPidFile(const Data &pidFile)
bool checkPosixProcessControl(const Data &dependentSettings)
SecurityTypes::TlsClientVerificationMode getConfigClientVerificationMode(const resip::Data &name, SecurityTypes::TlsClientVerificationMode defaultValue)
SecurityTypes::SSLType getConfigSSLType(const resip::Data &name, SecurityTypes::SSLType defaultValue)
bool getConfigValue(const resip::Data &name, resip::Uri &value)
Represents a SIP message.
This is the primary point of interaction between the app-layer and the stack.
Definition SipStack.hxx:160
void shutdownAndJoinThreads()
Shutdown and join any threads that the SipStack is running.
Definition SipStack.cxx:294
Security * getSecurity() const
Returns a pointer to the embedded Security object, 0 if not set.
void setExternalStatsHandler(ExternalStatsHandler *handler)
Installs a handler for the stacks internal StatisticsManager.
Definition SipStack.hxx:902
Transport * addTransport(TransportType protocol, int port, IpVersion version=V4, StunSetting stun=StunDisabled, const Data &ipInterface=Data::Empty, const Data &sipDomainname=Data::Empty, const Data &privateKeyPassPhrase=Data::Empty, SecurityTypes::SSLType sslType=SecurityTypes::DynamicTLS, unsigned transportFlags=0, const Data &certificateFilename="", const Data &privateKeyFilename="", SecurityTypes::TlsClientVerificationMode cvm=SecurityTypes::None, bool useEmailAsSIP=false, std::shared_ptr< WsConnectionValidator >=nullptr, std::shared_ptr< WsCookieContextFactory >=nullptr, const Data &netNs=Data::Empty)
Used by the application to add in a new built-in transport.
Definition SipStack.cxx:362
void setFixBadCSeqNumbers(bool pFixBadCSeqNumbers)
void addTransportSipMessageLoggingHandler(std::shared_ptr< Transport::SipMessageLoggingHandler > handler)
Used by the application to provide a handler that will get called for all inbound and outbound SIP me...
Definition SipStack.cxx:343
void registerTransactionUser(TransactionUser &, const bool front=false)
add a TU to the TU selection chain
void onReload()
reload configuration
Definition SipStack.cxx:317
void run()
Causes this SipStack object to create and run threads for carrying out processing.
Definition SipStack.cxx:258
Class used to specify what sub-system given sections of code belong to, for use by the logging system...
Definition Subsystem.hxx:34
static const char * Sips
Definition Symbols.hxx:63
static const char * Path
Definition Symbols.hxx:113
static const char * Outbound
Definition Symbols.hxx:114
static const char * Presence
Definition Symbols.hxx:103
static const char * Credential
Definition Symbols.hxx:123
static const char * Certificate
Definition Symbols.hxx:122
virtual void shutdown()
Definition ThreadIf.cxx:190
virtual void run()
Definition ThreadIf.cxx:75
static unsigned long TcpConnectTimeout
Definition Timer.hxx:127
static void resetT1(unsigned long t1)
Definition Timer.cxx:60
Represents the "token" element in the RFC 3261 grammar.
Definition Token.hxx:18
static uint64_t DnsGreylistDurationMs
The base-class for an RFC 3261 Transaction User.
void setMessageFilterRuleList(MessageFilterRuleList &rules)
Sets this TransactionUser's MessageFilterRuleList.
void setDomainMatcher(std::shared_ptr< DomainMatcher > domainMatcher) noexcept
Replaces the default DomainMatcher.
The base class for Transport classes.
Definition Transport.hxx:83
unsigned int getKey() const
virtual void setRcvBufLen(int buflen)
Represents a network address.
Definition Tuple.hxx:59
static const Data & toDataLower(TransportType type)
Definition Tuple.cxx:933
static TransportType toTransport(const Data &)
Converts a string representation of transport type, i.e.
Definition Tuple.cxx:921
Represents the "SIP-URI" and "SIPS-URI" elements in the RFC 3261 grammar.
Definition Uri.hxx:22
int & port()
Definition Uri.hxx:145
Data & host()
Definition Uri.hxx:40
const Data & param(const ExtensionParameter &param) const
Const accessor for non-natively-supported parameter types.
volatile bool & statisticsManagerEnabled()
Enable Statistics Manager.
void setEnumSuffixes(const std::vector< Data > &suffixes)
Specify which enum domains will be searched when sending.
void setFixBadDialogIdentifiers(bool pFixBadDialogIdentifiers)
Specify whether the stack should fix corrupted/changed dialog identifiers (ie, Call-Id and tags) in r...
void setEnumDomains(const std::map< Data, Data > &domains)
Specify which domains in the To: Uri will be subject to ENUM.
void setCongestionManager(CongestionManager *manager)
Sets the CongestionManager used by the stack.
void setStatisticsInterval(unsigned long seconds)
Sets the interval that determines the time between Statistics messages.
This Class is used to implement a primitive form of RPC using loose XML formatting.
SSLType
Note: Before adding to the SSLType enum, please see the comments about mTlsCtx in resip/stack/ssl/Sec...
dcm! – add UnusedChecking(_enum) below;
bool isEqualNoCase(const Data &left, const Data &right)
Definition Data.hxx:1116
std::vector< MessageFilterRule > MessageFilterRuleList
static const uint64_t NeverExpire
bool isSecure(TransportType type)
Returns true if passed in transport type is a secure transport protocol.
TransportType
An enumeration of transport protocols.
@ UNKNOWN_TRANSPORT
#define resipCout