/[resiprocate]/main/repro/ReproRunner.cxx
ViewVC logotype

Contents of /main/repro/ReproRunner.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11220 - (show annotations) (download)
Sat Aug 30 14:15:39 2014 UTC (5 years, 2 months ago) by dpocock
File size: 68594 byte(s)
repro: Logging: configuring Syslog facility
1 #if defined(HAVE_CONFIG_H)
2 #include "config.h"
3 #endif
4
5 #include <iostream>
6 #include <fstream>
7 #include <stdexcept>
8 #ifndef WIN32
9 #include <syslog.h>
10 #endif
11
12 #ifdef REPRO_DSO_PLUGINS
13
14 // in an autotools build, this is defined using pkglibdir
15 #ifndef REPRO_DSO_PLUGIN_DIR_DEFAULT
16 #define REPRO_DSO_PLUGIN_DIR_DEFAULT ""
17 #endif
18
19 // This is the UNIX way of doing DSO, an alternative implementation
20 // for Windows needs to include the relevant Windows headers here
21 // and implement the loader code further below
22 #include <dlfcn.h>
23
24 #endif
25
26 #include "rutil/Log.hxx"
27 #include "rutil/Logger.hxx"
28 #include "rutil/DnsUtil.hxx"
29 #include "rutil/dns/DnsStub.hxx"
30 #include "rutil/GeneralCongestionManager.hxx"
31 #include "rutil/TransportType.hxx"
32
33 #include "resip/stack/SipStack.hxx"
34 #include "resip/stack/Compression.hxx"
35 #include "resip/stack/EventStackThread.hxx"
36 #include "resip/stack/InteropHelper.hxx"
37 #include "resip/stack/ConnectionManager.hxx"
38 #include "resip/stack/WsCookieContextFactory.hxx"
39
40 #include "resip/dum/InMemorySyncRegDb.hxx"
41 #include "resip/dum/MasterProfile.hxx"
42 #include "resip/dum/DialogUsageManager.hxx"
43 #include "resip/dum/DumThread.hxx"
44 #include "resip/dum/TlsPeerAuthManager.hxx"
45 #include "resip/dum/WsCookieAuthManager.hxx"
46
47 #include "repro/AsyncProcessorWorker.hxx"
48 #include "repro/ReproRunner.hxx"
49 #include "repro/Proxy.hxx"
50 #include "repro/ProxyConfig.hxx"
51 #include "repro/BerkeleyDb.hxx"
52 #include "repro/Dispatcher.hxx"
53 #include "repro/UserAuthGrabber.hxx"
54 #include "repro/ProcessorChain.hxx"
55 #include "repro/ReproVersion.hxx"
56 #include "repro/WebAdmin.hxx"
57 #include "repro/WebAdminThread.hxx"
58 #include "repro/Registrar.hxx"
59 #include "repro/ReproAuthenticatorFactory.hxx"
60 #include "repro/ReproServerAuthManager.hxx"
61 #include "repro/RegSyncClient.hxx"
62 #include "repro/RegSyncServer.hxx"
63 #include "repro/RegSyncServerThread.hxx"
64 #include "repro/CommandServer.hxx"
65 #include "repro/CommandServerThread.hxx"
66 #include "repro/BasicWsConnectionValidator.hxx"
67 #include "repro/monkeys/CookieAuthenticator.hxx"
68 #include "repro/monkeys/IsTrustedNode.hxx"
69 #include "repro/monkeys/AmIResponsible.hxx"
70 #include "repro/monkeys/DigestAuthenticator.hxx"
71 #include "repro/monkeys/LocationServer.hxx"
72 #include "repro/monkeys/RecursiveRedirect.hxx"
73 #include "repro/monkeys/SimpleStaticRoute.hxx"
74 #include "repro/monkeys/StaticRoute.hxx"
75 #include "repro/monkeys/StrictRouteFixup.hxx"
76 #include "repro/monkeys/OutboundTargetHandler.hxx"
77 #include "repro/monkeys/QValueTargetHandler.hxx"
78 #include "repro/monkeys/SimpleTargetHandler.hxx"
79 #include "repro/monkeys/GeoProximityTargetSorter.hxx"
80 #include "repro/monkeys/RequestFilter.hxx"
81 #include "repro/monkeys/MessageSilo.hxx"
82 #include "repro/monkeys/CertificateAuthenticator.hxx"
83
84 #if defined(USE_SSL)
85 #include "repro/stateAgents/CertServer.hxx"
86 #include "resip/stack/ssl/Security.hxx"
87 #endif
88
89 #if defined(USE_MYSQL)
90 #include "repro/MySqlDb.hxx"
91 #endif
92
93 #include "rutil/WinLeakCheck.hxx"
94
95 #define RESIPROCATE_SUBSYSTEM resip::Subsystem::REPRO
96
97 using namespace resip;
98 using namespace repro;
99 using namespace std;
100
101 class ReproLogger : public ExternalLogger
102 {
103 public:
104 virtual ~ReproLogger() {}
105 /** return true to also do default logging, false to supress default logging. */
106 virtual bool operator()(Log::Level level,
107 const Subsystem& subsystem,
108 const Data& appName,
109 const char* file,
110 int line,
111 const Data& message,
112 const Data& messageWithHeaders)
113 {
114 // Log any errors to the screen
115 if(level <= Log::Err)
116 {
117 resipCout << messageWithHeaders << endl;
118 }
119 return true;
120 }
121 };
122 ReproLogger g_ReproLogger;
123
124 class ReproSipMessageLoggingHandler : public Transport::SipMessageLoggingHandler
125 {
126 public:
127 virtual ~ReproSipMessageLoggingHandler(){}
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
151 ReproRunner::ReproRunner()
152 : mRunning(false)
153 , mRestarting(false)
154 , mThreadedStack(false)
155 , mUseV4(true)
156 , mUseV6 (false)
157 , mRegSyncPort(0)
158 , mProxyConfig(0)
159 , mFdPollGrp(0)
160 , mAsyncProcessHandler(0)
161 , mSipStack(0)
162 , mStackThread(0)
163 , mAbstractDb(0)
164 , mRuntimeAbstractDb(0)
165 , mRegistrationPersistenceManager(0)
166 , mAuthFactory(0)
167 , mAsyncProcessorDispatcher(0)
168 , mMonkeys(0)
169 , mLemurs(0)
170 , mBaboons(0)
171 , mProxy(0)
172 , mWebAdminThread(0)
173 , mRegistrar(0)
174 , mDum(0)
175 , mDumThread(0)
176 , mCertServer(0)
177 , mRegSyncClient(0)
178 , mRegSyncServerV4(0)
179 , mRegSyncServerV6(0)
180 , mRegSyncServerThread(0)
181 , mCommandServerThread(0)
182 , mCongestionManager(0)
183 {
184 }
185
186 ReproRunner::~ReproRunner()
187 {
188 if(mRunning) shutdown();
189 }
190
191 bool
192 ReproRunner::run(int argc, char** argv)
193 {
194 if(mRunning) return false;
195
196 if(!mRestarting)
197 {
198 // Store original arc and argv - so we can reuse them on restart request
199 mArgc = argc;
200 mArgv = argv;
201 }
202
203 // Parse command line and configuration file
204 assert(!mProxyConfig);
205 Data defaultConfigFilename("repro.config");
206 try
207 {
208 mProxyConfig = new ProxyConfig();
209 mProxyConfig->parseConfig(mArgc, mArgv, defaultConfigFilename);
210 }
211 catch(BaseException& ex)
212 {
213 std::cerr << "Error parsing configuration: " << ex << std::endl;
214 #ifndef WIN32
215 syslog(LOG_DAEMON | LOG_CRIT, "%s", ex.getMessage().c_str());
216 #endif
217 return false;
218 }
219
220 // Non-Windows server process stuff
221 if(!mRestarting)
222 {
223 setPidFile(mProxyConfig->getConfigData("PidFile", "", true));
224
225 if(isAlreadyRunning())
226 {
227 std::cerr << "Already running, will not start two instances. Please stop existing process and/or delete PID file.";
228 #ifndef WIN32
229 syslog(LOG_DAEMON | LOG_CRIT, "Already running, will not start two instances. Please stop existing process and/or delete PID file.");
230 #endif
231 return false;
232 }
233
234 if(mProxyConfig->getConfigBool("Daemonize", false))
235 {
236 daemonize();
237 }
238 }
239
240 // Initialize resip logger
241 GenericLogImpl::MaxByteCount = mProxyConfig->getConfigUnsignedLong("LogFileMaxBytes", 5242880 /*5 Mb */);
242 Data loggingType = mProxyConfig->getConfigData("LoggingType", "cout", true);
243 Data syslogFacilityName = mProxyConfig->getConfigData("SyslogFacility", "LOG_DAEMON", true);
244 Log::initialize(loggingType,
245 mProxyConfig->getConfigData("LogLevel", "INFO", true),
246 mArgv[0],
247 mProxyConfig->getConfigData("LogFilename", "repro.log", true).c_str(),
248 isEqualNoCase(loggingType, "file") ? &g_ReproLogger : 0, // if logging to file then write WARNINGS, and Errors to console still
249 syslogFacilityName);
250
251 InfoLog( << "Starting repro version " << VersionUtils::instance().releaseVersion() << "...");
252
253 // Create SipStack and associated objects
254 if(!createSipStack())
255 {
256 return false;
257 }
258
259 // Load the plugins after creating the stack, as they may need it
260 if(!loadPlugins())
261 {
262 return false;
263 }
264
265 // Drop privileges (can do this now that sockets are bound)
266 Data runAsUser = mProxyConfig->getConfigData("RunAsUser", "", true);
267 Data runAsGroup = mProxyConfig->getConfigData("RunAsGroup", "", true);
268 if(!runAsUser.empty())
269 {
270 InfoLog( << "Trying to drop privileges, configured uid = " << runAsUser << " gid = " << runAsGroup);
271 dropPrivileges(runAsUser, runAsGroup);
272 }
273
274 // Create datastore
275 if(!createDatastore())
276 {
277 return false;
278 }
279
280 // Create authentication mechanism
281 createAuthenticatorFactory();
282
283 // Create DialogUsageManager that handles ServerRegistration,
284 // and potentially certificate subscription server
285 createDialogUsageManager();
286
287 // Create the Proxy and associate objects
288 if(!createProxy())
289 {
290 return false;
291 }
292
293 // Create HTTP WebAdmin and Thread
294 if(!createWebAdmin())
295 {
296 return false;
297 }
298
299 // Create reg sync components if required
300 createRegSync();
301
302 // Create command server if required
303 if(!mRestarting)
304 {
305 createCommandServer();
306 }
307
308 // Make it all go - startup all threads
309 mThreadedStack = mProxyConfig->getConfigBool("ThreadedStack", true);
310 if(mThreadedStack)
311 {
312 // If configured, then start the sub-threads within the stack
313 mSipStack->run();
314 }
315 mStackThread->run();
316 if(mDumThread)
317 {
318 mDumThread->run();
319 }
320 mProxy->run();
321 if(mWebAdminThread)
322 {
323 mWebAdminThread->run();
324 }
325 if(!mRestarting && mCommandServerThread)
326 {
327 mCommandServerThread->run();
328 }
329 if(mRegSyncServerThread)
330 {
331 mRegSyncServerThread->run();
332 }
333 if(mRegSyncClient)
334 {
335 mRegSyncClient->run();
336 }
337
338 mRunning = true;
339
340 return true;
341 }
342
343 void
344 ReproRunner::shutdown()
345 {
346 if(!mRunning) return;
347
348 // Tell all threads to shutdown
349 if(mWebAdminThread)
350 {
351 mWebAdminThread->shutdown();
352 }
353 if(mDumThread)
354 {
355 mDumThread->shutdown();
356 }
357 mProxy->shutdown();
358 mStackThread->shutdown();
359 if(!mRestarting && mCommandServerThread) // leave command server running if we are restarting
360 {
361 mCommandServerThread->shutdown();
362 }
363 if(mRegSyncServerThread)
364 {
365 mRegSyncServerThread->shutdown();
366 }
367 if(mRegSyncClient)
368 {
369 mRegSyncClient->shutdown();
370 }
371
372 // Wait for all threads to shutdown, and destroy objects
373 mProxy->join();
374 if(mThreadedStack)
375 {
376 mSipStack->shutdownAndJoinThreads();
377 }
378 mStackThread->join();
379 if(mWebAdminThread)
380 {
381 mWebAdminThread->join();
382 }
383 if(mDumThread)
384 {
385 mDumThread->join();
386 }
387 if(mAuthFactory)
388 {
389 // Both proxy and dum threads are down at this point, we can
390 // destroy the authFactory and its authRequest dispatcher
391 // and associated threads now
392 delete mAuthFactory;
393 mAuthFactory = 0;
394 }
395 if(mAsyncProcessorDispatcher)
396 {
397 // Both proxy and dum threads are down at this point, we can
398 // destroy the async processor dispatcher and associated threads now
399 delete mAsyncProcessorDispatcher;
400 mAsyncProcessorDispatcher = 0;
401 }
402 if(!mRestarting && mCommandServerThread) // we leave command server running during restart
403 {
404 mCommandServerThread->join();
405 }
406 if(mRegSyncServerThread)
407 {
408 mRegSyncServerThread->join();
409 }
410 if(mRegSyncClient)
411 {
412 mRegSyncClient->join();
413 }
414
415 mSipStack->setCongestionManager(0);
416
417 cleanupObjects();
418 mRunning = false;
419 }
420
421 void
422 ReproRunner::restart()
423 {
424 if(!mRunning) return;
425 mRestarting = true;
426 shutdown();
427 run(0, 0);
428 mRestarting = false;
429 }
430
431 void
432 ReproRunner::onHUP()
433 {
434 // Let the plugins know
435 std::vector<Plugin*>::iterator it;
436 for(it = mPlugins.begin(); it != mPlugins.end(); it++)
437 {
438 (*it)->onReload();
439 }
440 }
441
442 void
443 ReproRunner::cleanupObjects()
444 {
445 delete mCongestionManager; mCongestionManager = 0;
446 if(!mRestarting)
447 {
448 // We leave command server running during restart
449 delete mCommandServerThread; mCommandServerThread = 0;
450 for(std::list<CommandServer*>::iterator it = mCommandServerList.begin(); it != mCommandServerList.end(); it++)
451 {
452 delete (*it);
453 }
454 mCommandServerList.clear();
455 }
456 delete mRegSyncServerThread; mRegSyncServerThread = 0;
457 delete mRegSyncServerV6; mRegSyncServerV6 = 0;
458 delete mRegSyncServerV4; mRegSyncServerV4 = 0;
459 delete mRegSyncClient; mRegSyncClient = 0;
460 #if defined(USE_SSL)
461 delete mCertServer; mCertServer = 0;
462 #endif
463 delete mDumThread; mDumThread = 0;
464 delete mDum; mDum = 0;
465 delete mRegistrar; mRegistrar = 0;
466 delete mWebAdminThread; mWebAdminThread = 0;
467 for(std::list<WebAdmin*>::iterator it = mWebAdminList.begin(); it != mWebAdminList.end(); it++)
468 {
469 delete (*it);
470 }
471 mWebAdminList.clear();
472 delete mProxy; mProxy = 0;
473 delete mBaboons; mBaboons = 0;
474 delete mLemurs; mLemurs = 0;
475 delete mMonkeys; mMonkeys = 0;
476 delete mAuthFactory; mAuthFactory = 0;
477 delete mAsyncProcessorDispatcher; mAsyncProcessorDispatcher = 0;
478 if(!mRestarting)
479 {
480 // If we are restarting then leave the In Memory Registration database intact
481 delete mRegistrationPersistenceManager; mRegistrationPersistenceManager = 0;
482 }
483 delete mAbstractDb; mAbstractDb = 0;
484 delete mRuntimeAbstractDb; mRuntimeAbstractDb = 0;
485 delete mStackThread; mStackThread = 0;
486 delete mSipStack; mSipStack = 0;
487 delete mAsyncProcessHandler; mAsyncProcessHandler = 0;
488 delete mFdPollGrp; mFdPollGrp = 0;
489 delete mProxyConfig; mProxyConfig = 0;
490 }
491
492 bool
493 ReproRunner::loadPlugins()
494 {
495 std::vector<Data> pluginNames;
496 mProxyConfig->getConfigValue("LoadPlugins", pluginNames);
497
498 #ifdef REPRO_DSO_PLUGINS
499 if(pluginNames.empty())
500 {
501 DebugLog(<<"LoadPlugins not specified, not attempting to load any plugins");
502 return true;
503 }
504
505 const Data& pluginDirectory = mProxyConfig->getConfigData("PluginDirectory", REPRO_DSO_PLUGIN_DIR_DEFAULT, true);
506 if(pluginDirectory.empty())
507 {
508 ErrLog(<<"LoadPlugins specified but PluginDirectory not specified, can't load plugins");
509 return false;
510 }
511 for(std::vector<Data>::iterator it = pluginNames.begin(); it != pluginNames.end(); it++)
512 {
513 void *dlib;
514 // FIXME:
515 // - not all platforms use the .so extension
516 // - detect and use correct directory separator charactor
517 // - do we need to support relative paths here?
518 // - should we use the filename prefix 'lib', 'mod' or something else?
519 Data name = pluginDirectory + '/' + "lib" + *it + ".so";
520 dlib = dlopen(name.c_str(), RTLD_NOW | RTLD_GLOBAL);
521 if(!dlib)
522 {
523 ErrLog(<< "Failed to load plugin " << *it << " (" << name << "): " << dlerror());
524 return false;
525 }
526 ReproPluginDescriptor* desc = (ReproPluginDescriptor*)dlsym(dlib, "reproPluginDesc");
527 if(!desc)
528 {
529 ErrLog(<< "Failed to find reproPluginDesc in plugin " << *it << " (" << name << "): " << dlerror());
530 return false;
531 }
532 if(!(desc->mPluginApiVersion == REPRO_DSO_PLUGIN_API_VERSION))
533 {
534 ErrLog(<< "Failed to load plugin " << *it << " (" << name << "): found version " << desc->mPluginApiVersion << ", expecting version " << REPRO_DSO_PLUGIN_API_VERSION);
535 }
536 DebugLog(<<"Trying to instantiate plugin " << *it);
537 // Instantiate the plugin object and add it to our runtime environment
538 Plugin* plugin = desc->creationFunc();
539 if(!plugin)
540 {
541 ErrLog(<< "Failed to instantiate plugin " << *it << " (" << name << ")");
542 return false;
543 }
544 if(!plugin->init(*mSipStack, mProxyConfig))
545 {
546 ErrLog(<< "Failed to initialize plugin " << *it << " (" << name << ")");
547 return false;
548 }
549 mPlugins.push_back(plugin);
550 }
551 return true;
552 #else
553 if(!pluginNames.empty())
554 {
555 ErrLog(<<"LoadPlugins specified but repro not compiled with plugin DSO support");
556 return false;
557 }
558 DebugLog(<<"Not compiled with plugin DSO support");
559 return true;
560 #endif
561 }
562
563 bool
564 ReproRunner::createSipStack()
565 {
566 // Override T1 timer if configured to do so
567 unsigned long overrideT1 = mProxyConfig->getConfigInt("TimerT1", 0);
568 if(overrideT1)
569 {
570 WarningLog(<< "Overriding T1! (new value is " <<
571 overrideT1 << ")");
572 resip::Timer::resetT1(overrideT1);
573 }
574
575 unsigned long messageSizeLimit = mProxyConfig->getConfigUnsignedLong("StreamMessageSizeLimit", 0);
576 if(messageSizeLimit > 0)
577 {
578 DebugLog(<< "Using maximum message size "<< messageSizeLimit << " on stream-based transports");
579 ConnectionBase::setMessageSizeMax(messageSizeLimit);
580 }
581
582 // Create Security (TLS / Certificates) and Compression (SigComp) objects if
583 // pre-precessor defines are enabled
584 Security* security = 0;
585 Compression* compression = 0;
586 #ifdef USE_SSL
587 Data certPath = mProxyConfig->getConfigData("CertificatePath", "");
588 if(certPath.empty())
589 {
590 security = new Security(Security::ExportableSuite, mProxyConfig->getConfigData("TLSPrivateKeyPassPhrase", ""));
591 }
592 else
593 {
594 security = new Security(certPath, Security::ExportableSuite, mProxyConfig->getConfigData("TLSPrivateKeyPassPhrase", ""));
595 }
596 Data caDir;
597 mProxyConfig->getConfigValue("CADirectory", caDir);
598 if(!caDir.empty())
599 {
600 security->addCADirectory(caDir);
601 }
602 Data caFile;
603 mProxyConfig->getConfigValue("CAFile", caFile);
604 if(!caFile.empty())
605 {
606 security->addCAFile(caFile);
607 }
608 #endif
609
610 #ifdef USE_SIGCOMP
611 compression = new Compression(Compression::DEFLATE);
612 #endif
613
614 // Create EventThreadInterruptor used to wake up the stack for
615 // for reasons other than an Fd signalling
616 assert(!mFdPollGrp);
617 mFdPollGrp = FdPollGrp::create();
618 assert(!mAsyncProcessHandler);
619 mAsyncProcessHandler = new EventThreadInterruptor(*mFdPollGrp);
620
621 // Set Flags that will enable/disable IPv4 and/or IPv6, based on
622 // configuration and pre-processor flags
623 mUseV4 = !mProxyConfig->getConfigBool("DisableIPv4", false);
624 #ifdef USE_IPV6
625 mUseV6 = mProxyConfig->getConfigBool("EnableIPv6", true);
626 #else
627 bool useV6 = false;
628 #endif
629 if (mUseV4) InfoLog (<< "V4 enabled");
630 if (mUseV6) InfoLog (<< "V6 enabled");
631
632 // Build DNS Server list from config
633 DnsStub::NameserverList dnsServers;
634 std::vector<resip::Data> dnsServersConfig;
635 mProxyConfig->getConfigValue("DNSServers", dnsServersConfig);
636 for(std::vector<resip::Data>::iterator it = dnsServersConfig.begin(); it != dnsServersConfig.end(); it++)
637 {
638 if((mUseV4 && DnsUtil::isIpV4Address(*it)) || (mUseV6 && DnsUtil::isIpV6Address(*it)))
639 {
640 InfoLog(<< "Using DNS Server from config: " << *it);
641 dnsServers.push_back(Tuple(*it, 0, UNKNOWN_TRANSPORT).toGenericIPAddress());
642 }
643 }
644
645 // Create the SipStack Object
646 assert(!mSipStack);
647 mSipStack = new SipStack(security,
648 dnsServers,
649 mAsyncProcessHandler,
650 /*stateless*/false,
651 /*socketFunc*/0,
652 compression,
653 mFdPollGrp);
654
655 // Set any enum suffixes from configuration
656 std::vector<Data> enumSuffixes;
657 mProxyConfig->getConfigValue("EnumSuffixes", enumSuffixes);
658 if (enumSuffixes.size() > 0)
659 {
660 mSipStack->setEnumSuffixes(enumSuffixes);
661 }
662
663 // Set any enum domains from configuration
664 std::map<Data,Data> enumDomains;
665 std::vector<Data> _enumDomains;
666 mProxyConfig->getConfigValue("EnumDomains", _enumDomains);
667 if (enumSuffixes.size() > 0)
668 {
669 for(std::vector<Data>::iterator it = _enumDomains.begin(); it != _enumDomains.end(); it++)
670 {
671 enumDomains[*it] = *it;
672 }
673 mSipStack->setEnumDomains(enumDomains);
674 }
675
676 // Add External Stats handler
677 mSipStack->setExternalStatsHandler(this);
678
679 // Set Transport SipMessage Logging Handler - if enabled
680 if(mProxyConfig->getConfigBool("EnableSipMessageLogging", false))
681 {
682 mSipStack->setTransportSipMessageLoggingHandler(SharedPtr<ReproSipMessageLoggingHandler>(new ReproSipMessageLoggingHandler));
683 }
684
685 // Add stack transports
686 bool allTransportsSpecifyRecordRoute=false;
687 if(!addTransports(allTransportsSpecifyRecordRoute))
688 {
689 cleanupObjects();
690 return false;
691 }
692
693 // Enable and configure RFC5626 Outbound support
694 InteropHelper::setOutboundVersion(mProxyConfig->getConfigInt("OutboundVersion", 5626));
695 InteropHelper::setOutboundSupported(mProxyConfig->getConfigBool("DisableOutbound", false) ? false : true);
696 InteropHelper::setRRTokenHackEnabled(mProxyConfig->getConfigBool("EnableFlowTokens", false));
697 InteropHelper::setAssumeFirstHopSupportsOutboundEnabled(mProxyConfig->getConfigBool("AssumeFirstHopSupportsOutbound", false));
698 Data clientNATDetectionMode = mProxyConfig->getConfigData("ClientNatDetectionMode", "DISABLED");
699 if(isEqualNoCase(clientNATDetectionMode, "ENABLED"))
700 {
701 InteropHelper::setClientNATDetectionMode(InteropHelper::ClientNATDetectionEnabled);
702 }
703 else if(isEqualNoCase(clientNATDetectionMode, "PRIVATE_TO_PUBLIC"))
704 {
705 InteropHelper::setClientNATDetectionMode(InteropHelper::ClientNATDetectionPrivateToPublicOnly);
706 }
707 ConnectionManager::MinimumGcHeadroom = mProxyConfig->getConfigUnsignedLong("TCPMinimumGCHeadroom", 0);
708 unsigned long tcpConnectionGCAge = mProxyConfig->getConfigUnsignedLong("TCPConnectionGCAge", 0);
709 if(tcpConnectionGCAge > 0)
710 {
711 ConnectionManager::MinimumGcAge = tcpConnectionGCAge * 1000;
712 ConnectionManager::EnableAgressiveGc = true;
713 }
714 unsigned long outboundFlowTimer = mProxyConfig->getConfigUnsignedLong("FlowTimer", 0);
715 if(outboundFlowTimer > 0)
716 {
717 InteropHelper::setFlowTimerSeconds(outboundFlowTimer);
718 if(tcpConnectionGCAge == 0)
719 {
720 // This should be set too when using outboundFlowTimer
721 ConnectionManager::MinimumGcAge = 7200000;
722 }
723 ConnectionManager::EnableAgressiveGc = true;
724 }
725
726 // Check Path and RecordRoute settings, print warning if features are enabled that
727 // require record-routing and record-route uri(s) is not configured
728 bool assumePath = mProxyConfig->getConfigBool("AssumePath", false);
729 bool forceRecordRoute = mProxyConfig->getConfigBool("ForceRecordRouting", false);
730 Uri recordRouteUri;
731 mProxyConfig->getConfigValue("RecordRouteUri", recordRouteUri);
732 if((InteropHelper::getOutboundSupported()
733 || InteropHelper::getRRTokenHackEnabled()
734 || InteropHelper::getClientNATDetectionMode() != InteropHelper::ClientNATDetectionDisabled
735 || assumePath
736 || forceRecordRoute
737 )
738 && !(allTransportsSpecifyRecordRoute || !recordRouteUri.host().empty()))
739 {
740 CritLog(<< "In order for outbound support, the Record-Route flow-token"
741 " hack, or force-record-route to work, you MUST specify a Record-Route URI. Launching "
742 "without...");
743 InteropHelper::setOutboundSupported(false);
744 InteropHelper::setRRTokenHackEnabled(false);
745 InteropHelper::setClientNATDetectionMode(InteropHelper::ClientNATDetectionDisabled);
746 assumePath = false;
747 forceRecordRoute=false;
748 }
749
750 // Configure misc. stack settings
751 mSipStack->setFixBadDialogIdentifiers(false);
752 mSipStack->setFixBadCSeqNumbers(false);
753 int statsLogInterval = mProxyConfig->getConfigInt("StatisticsLogInterval", 60);
754 if(statsLogInterval > 0)
755 {
756 mSipStack->setStatisticsInterval(statsLogInterval);
757 mSipStack->statisticsManagerEnabled() = true;
758 }
759 else
760 {
761 mSipStack->statisticsManagerEnabled() = false;
762 }
763
764 // Create Congestion Manager, if required
765 assert(!mCongestionManager);
766 if(mProxyConfig->getConfigBool("CongestionManagement", true))
767 {
768 Data metricData = mProxyConfig->getConfigData("CongestionManagementMetric", "WAIT_TIME", true);
769 GeneralCongestionManager::MetricType metric = GeneralCongestionManager::WAIT_TIME;
770 if(isEqualNoCase(metricData, "TIME_DEPTH"))
771 {
772 metric = GeneralCongestionManager::TIME_DEPTH;
773 }
774 else if(isEqualNoCase(metricData, "SIZE"))
775 {
776 metric = GeneralCongestionManager::SIZE;
777 }
778 else if(!isEqualNoCase(metricData, "WAIT_TIME"))
779 {
780 WarningLog( << "CongestionManagementMetric specified as an unknown value (" << metricData << "), defaulting to WAIT_TIME.");
781 }
782 mCongestionManager = new GeneralCongestionManager(
783 metric,
784 mProxyConfig->getConfigUnsignedLong("CongestionManagementTolerance", 200));
785 mSipStack->setCongestionManager(mCongestionManager);
786 }
787
788 // Create base thread to run stack in (note: stack may use other sub-threads, depending on configuration)
789 assert(!mStackThread);
790 mStackThread = new EventStackThread(*mSipStack,
791 *dynamic_cast<EventThreadInterruptor*>(mAsyncProcessHandler),
792 *mFdPollGrp);
793 return true;
794 }
795
796 bool
797 ReproRunner::createDatastore()
798 {
799 // Create Database access objects
800 assert(!mAbstractDb);
801 assert(!mRuntimeAbstractDb);
802 #ifdef USE_MYSQL
803 Data mySQLServer;
804 mProxyConfig->getConfigValue("MySQLServer", mySQLServer);
805 if(!mySQLServer.empty())
806 {
807 mAbstractDb = new MySqlDb(mySQLServer,
808 mProxyConfig->getConfigData("MySQLUser", ""),
809 mProxyConfig->getConfigData("MySQLPassword", ""),
810 mProxyConfig->getConfigData("MySQLDatabaseName", ""),
811 mProxyConfig->getConfigUnsignedLong("MySQLPort", 0),
812 mProxyConfig->getConfigData("MySQLCustomUserAuthQuery", ""));
813 }
814 Data runtimeMySQLServer;
815 mProxyConfig->getConfigValue("RuntimeMySQLServer", runtimeMySQLServer);
816 if(!runtimeMySQLServer.empty())
817 {
818 mRuntimeAbstractDb = new MySqlDb(runtimeMySQLServer,
819 mProxyConfig->getConfigData("RuntimeMySQLUser", ""),
820 mProxyConfig->getConfigData("RuntimeMySQLPassword", ""),
821 mProxyConfig->getConfigData("RuntimeMySQLDatabaseName", ""),
822 mProxyConfig->getConfigUnsignedLong("RuntimeMySQLPort", 0),
823 mProxyConfig->getConfigData("MySQLCustomUserAuthQuery", ""));
824 }
825 #endif
826 if (!mAbstractDb)
827 {
828 mAbstractDb = new BerkeleyDb(mProxyConfig->getConfigData("DatabasePath", "./", true));
829 }
830 assert(mAbstractDb);
831 if(!mAbstractDb->isSane())
832 {
833 CritLog(<<"Failed to open configuration database");
834 cleanupObjects();
835 return false;
836 }
837 if(mRuntimeAbstractDb && !mRuntimeAbstractDb->isSane())
838 {
839 CritLog(<<"Failed to open runtime configuration database");
840 cleanupObjects();
841 return false;
842 }
843 mProxyConfig->createDataStore(mAbstractDb, mRuntimeAbstractDb);
844
845 // Create ImMemory Registration Database
846 mRegSyncPort = mProxyConfig->getConfigInt("RegSyncPort", 0);
847 // We only need removed records to linger if we have reg sync enabled
848 if(!mRestarting) // If we are restarting then we left the InMemoryRegistrationDb intact at shutdown - don't recreate
849 {
850 assert(!mRegistrationPersistenceManager);
851 mRegistrationPersistenceManager = new InMemorySyncRegDb(mRegSyncPort ? 86400 /* 24 hours */ : 0 /* removeLingerSecs */); // !slg! could make linger time a setting
852 }
853 assert(mRegistrationPersistenceManager);
854
855 // Copy contacts from the StaticRegStore to the RegistrationPersistanceManager
856 populateRegistrations();
857
858 return true;
859 }
860
861 void
862 ReproRunner::createAuthenticatorFactory()
863 {
864 // TODO: let a plugin supply an instance of AuthenticatorFactory
865 // instead of our builtin ReproAuthenticatorFactory
866 mAuthFactory = new ReproAuthenticatorFactory(*mProxyConfig, *mSipStack, mDum);
867 }
868
869 void
870 ReproRunner::createDialogUsageManager()
871 {
872 // Create Profile settings for DUM Instance that handles ServerRegistration,
873 // and potentially certificate subscription server
874 SharedPtr<MasterProfile> profile(new MasterProfile);
875 profile->clearSupportedMethods();
876 profile->addSupportedMethod(resip::REGISTER);
877 #ifdef USE_SSL
878 profile->addSupportedScheme(Symbols::Sips);
879 #endif
880 if(InteropHelper::getOutboundSupported())
881 {
882 profile->addSupportedOptionTag(Token(Symbols::Outbound));
883 }
884 profile->addSupportedOptionTag(Token(Symbols::Path));
885 if(mProxyConfig->getConfigBool("AllowBadReg", false))
886 {
887 profile->allowBadRegistrationEnabled() = true;
888 }
889 #ifdef PACKAGE_VERSION
890 Data serverText(mProxyConfig->getConfigData("ServerText", "repro " PACKAGE_VERSION));
891 #else
892 Data serverText(mProxyConfig->getConfigData("ServerText", ""));
893 #endif
894 if(!serverText.empty())
895 {
896 profile->setUserAgent(serverText);
897 }
898
899 // Create DialogeUsageManager if Registrar or Certificate Server are enabled
900 assert(!mRegistrar);
901 assert(!mDum);
902 assert(!mDumThread);
903 mRegistrar = new Registrar;
904 resip::MessageFilterRuleList ruleList;
905 bool registrarEnabled = !mProxyConfig->getConfigBool("DisableRegistrar", false);
906 bool certServerEnabled = mProxyConfig->getConfigBool("EnableCertServer", false);
907 if (registrarEnabled || certServerEnabled)
908 {
909 mDum = new DialogUsageManager(*mSipStack);
910 mDum->setMasterProfile(profile);
911 addDomains(*mDum, false /* log? already logged when adding to Proxy - no need to log again*/);
912 }
913
914 // If registrar is enabled, configure DUM to handle REGISTER requests
915 if (registrarEnabled)
916 {
917 assert(mDum);
918 assert(mRegistrationPersistenceManager);
919 mDum->setServerRegistrationHandler(mRegistrar);
920 mDum->setRegistrationPersistenceManager(mRegistrationPersistenceManager);
921
922 // Install rules so that the registrar only gets REGISTERs
923 resip::MessageFilterRule::MethodList methodList;
924 methodList.push_back(resip::REGISTER);
925 ruleList.push_back(MessageFilterRule(resip::MessageFilterRule::SchemeList(),
926 resip::MessageFilterRule::DomainIsMe,
927 methodList) );
928 }
929
930 // If Certificate Server is enabled, configure DUM to handle SUBSCRIBE and
931 // PUBLISH requests for events: credential and certificate
932 assert(!mCertServer);
933 if (certServerEnabled)
934 {
935 #if defined(USE_SSL)
936 mCertServer = new CertServer(*mDum);
937
938 // Install rules so that the cert server receives SUBSCRIBEs and PUBLISHs
939 resip::MessageFilterRule::MethodList methodList;
940 resip::MessageFilterRule::EventList eventList;
941 methodList.push_back(resip::SUBSCRIBE);
942 methodList.push_back(resip::PUBLISH);
943 eventList.push_back(resip::Symbols::Credential);
944 eventList.push_back(resip::Symbols::Certificate);
945 ruleList.push_back(MessageFilterRule(resip::MessageFilterRule::SchemeList(),
946 resip::MessageFilterRule::DomainIsMe,
947 methodList,
948 eventList));
949 #endif
950 }
951
952 if (mDum)
953 {
954 assert(mAuthFactory);
955 mAuthFactory->setDum(mDum);
956
957 if(mAuthFactory->certificateAuthEnabled())
958 {
959 // TODO: perhaps this should be initialised from the trusted node
960 // monkey? Or should the list of trusted TLS peers be independent
961 // from the trusted node list?
962 mDum->addIncomingFeature(mAuthFactory->getCertificateAuthManager());
963 }
964
965 Data wsCookieAuthSharedSecret = mProxyConfig->getConfigData("WSCookieAuthSharedSecret", "");
966 if(!mAuthFactory->digestAuthEnabled() && !wsCookieAuthSharedSecret.empty())
967 {
968 SharedPtr<WsCookieAuthManager> cookieAuth(new WsCookieAuthManager(*mDum, mDum->dumIncomingTarget()));
969 mDum->addIncomingFeature(cookieAuth);
970 }
971
972 // If Authentication is enabled, then configure DUM to authenticate requests
973 if (mAuthFactory->digestAuthEnabled())
974 {
975 mDum->setServerAuthManager(mAuthFactory->getServerAuthManager());
976 }
977
978 // Set the MessageFilterRuleList on DUM and create a thread to run DUM in
979 mDum->setMessageFilterRuleList(ruleList);
980 mDumThread = new DumThread(*mDum);
981 }
982 }
983
984 bool
985 ReproRunner::createProxy()
986 {
987 // Create AsyncProcessorDispatcher thread pool that is shared by the processsors for
988 // any asyncronous tasks (ie: RequestFilter and MessageSilo processors)
989 int numAsyncProcessorWorkerThreads = mProxyConfig->getConfigInt("NumAsyncProcessorWorkerThreads", 2);
990 if(numAsyncProcessorWorkerThreads > 0)
991 {
992 assert(!mAsyncProcessorDispatcher);
993 mAsyncProcessorDispatcher = new Dispatcher(std::auto_ptr<Worker>(new AsyncProcessorWorker),
994 mSipStack,
995 numAsyncProcessorWorkerThreads);
996 }
997
998 std::vector<Plugin*>::iterator it;
999
1000 // Create proxy processor chains
1001 /* Explanation: "Monkeys" are processors which operate on incoming requests
1002 "Lemurs" are processors which operate on incoming responses
1003 "Baboons" are processors which operate on a request for each target
1004 as the request is about to be forwarded to that target */
1005 // Make Monkeys
1006 assert(!mMonkeys);
1007 mMonkeys = new ProcessorChain(Processor::REQUEST_CHAIN);
1008 makeRequestProcessorChain(*mMonkeys);
1009 InfoLog(<< *mMonkeys);
1010 for(it = mPlugins.begin(); it != mPlugins.end(); it++)
1011 {
1012 (*it)->onRequestProcessorChainPopulated(*mMonkeys);
1013 }
1014
1015 // Make Lemurs
1016 assert(!mLemurs);
1017 mLemurs = new ProcessorChain(Processor::RESPONSE_CHAIN);
1018 makeResponseProcessorChain(*mLemurs);
1019 InfoLog(<< *mLemurs);
1020 for(it = mPlugins.begin(); it != mPlugins.end(); it++)
1021 {
1022 (*it)->onResponseProcessorChainPopulated(*mLemurs);
1023 }
1024
1025 // Make Baboons
1026 assert(!mBaboons);
1027 mBaboons = new ProcessorChain(Processor::TARGET_CHAIN);
1028 makeTargetProcessorChain(*mBaboons);
1029 InfoLog(<< *mBaboons);
1030 for(it = mPlugins.begin(); it != mPlugins.end(); it++)
1031 {
1032 (*it)->onTargetProcessorChainPopulated(*mBaboons);
1033 }
1034
1035 // Create main Proxy class
1036 assert(!mProxy);
1037 mProxy = new Proxy(*mSipStack,
1038 *mProxyConfig,
1039 *mMonkeys,
1040 *mLemurs,
1041 *mBaboons);
1042 Data defaultRealm = addDomains(*mProxy, true);
1043 mHttpRealm = mProxyConfig->getConfigData("HttpAdminRealm", defaultRealm);
1044
1045 // Set Server Text
1046 #ifdef PACKAGE_VERSION
1047 Data serverText(mProxyConfig->getConfigData("ServerText", "repro " PACKAGE_VERSION));
1048 #else
1049 Data serverText(mProxyConfig->getConfigData("ServerText", ""));
1050 #endif
1051 if(!serverText.empty())
1052 {
1053 mProxy->setServerText(serverText);
1054 }
1055
1056 // Register the Proxy class a stack transaction user
1057 // Note: This is done after creating the DialogUsageManager so that it acts
1058 // like a catchall and will handle all requests the DUM does not
1059 mSipStack->registerTransactionUser(*mProxy);
1060
1061 // Map the Registrar to the Proxy
1062 if(mRegistrar)
1063 {
1064 mRegistrar->setProxy(mProxy);
1065 }
1066
1067 // Add the transport specific RecordRoutes that were stored in addTransports to the Proxy
1068 for(TransportRecordRouteMap::iterator it = mStartupTransportRecordRoutes.begin();
1069 it != mStartupTransportRecordRoutes.end(); it++)
1070 {
1071 mProxy->addTransportRecordRoute(it->first, it->second);
1072 }
1073
1074 return true;
1075 }
1076
1077 void
1078 ReproRunner::populateRegistrations()
1079 {
1080 assert(mRegistrationPersistenceManager);
1081 assert(mProxyConfig);
1082 assert(mProxyConfig->getDataStore());
1083
1084 // Copy contacts from the StaticRegStore to the RegistrationPersistanceManager
1085 StaticRegStore::StaticRegRecordMap& staticRegList = mProxyConfig->getDataStore()->mStaticRegStore.getStaticRegList();
1086 StaticRegStore::StaticRegRecordMap::iterator it = staticRegList.begin();
1087 for(; it != staticRegList.end(); it++)
1088 {
1089 try
1090 {
1091 Uri aor(it->second.mAor);
1092
1093 ContactInstanceRecord rec;
1094 rec.mContact = NameAddr(it->second.mContact);
1095 rec.mSipPath = NameAddrs(it->second.mPath);
1096 rec.mRegExpires = NeverExpire;
1097 rec.mSyncContact = true; // Tag this permanent contact as being a syncronized contact so that it will
1098 // be syncronized to a paired server (this is actually configuration information)
1099 mRegistrationPersistenceManager->updateContact(aor, rec);
1100 }
1101 catch(resip::ParseBuffer::Exception& e)
1102 {
1103 // This should never happen, since the format should be verified before writing to DB
1104 ErrLog(<<"Failed to apply a static registration due to parse error: " << e);
1105 }
1106 }
1107 }
1108
1109 bool
1110 ReproRunner::createWebAdmin()
1111 {
1112 assert(mWebAdminList.empty());
1113 assert(!mWebAdminThread);
1114
1115 std::vector<resip::Data> httpServerBindAddresses;
1116 mProxyConfig->getConfigValue("HttpBindAddress", httpServerBindAddresses);
1117 int httpPort = mProxyConfig->getConfigInt("HttpPort", 5080);
1118
1119 if(httpPort)
1120 {
1121 if(httpServerBindAddresses.empty())
1122 {
1123 if(mUseV4)
1124 {
1125 httpServerBindAddresses.push_back("0.0.0.0");
1126 }
1127 if(mUseV6)
1128 {
1129 httpServerBindAddresses.push_back("::");
1130 }
1131 }
1132
1133 for(std::vector<resip::Data>::iterator it = httpServerBindAddresses.begin(); it != httpServerBindAddresses.end(); it++)
1134 {
1135 if(mUseV4 && DnsUtil::isIpV4Address(*it))
1136 {
1137 WebAdmin* webAdminV4 = 0;
1138
1139 try
1140 {
1141 webAdminV4 = new WebAdmin(*mProxy,
1142 *mRegistrationPersistenceManager,
1143 mHttpRealm,
1144 httpPort,
1145 V4,
1146 *it);
1147 }
1148 catch(WebAdmin::ConfigException& ex)
1149 {
1150 ErrLog(<<"Exception when starting WebAdmin: " << ex.getMessage());
1151 webAdminV4 = 0;
1152 }
1153
1154 if (!webAdminV4 || !webAdminV4->isSane())
1155 {
1156 CritLog(<<"Failed to start WebAdminV4");
1157 delete webAdminV4;
1158 cleanupObjects();
1159 return false;
1160 }
1161
1162 mWebAdminList.push_back(webAdminV4);
1163 }
1164
1165 if(mUseV6 && DnsUtil::isIpV6Address(*it))
1166 {
1167 WebAdmin* webAdminV6 = 0;
1168
1169 try
1170 {
1171 webAdminV6 = new WebAdmin(*mProxy,
1172 *mRegistrationPersistenceManager,
1173 mHttpRealm,
1174 httpPort,
1175 V6,
1176 *it);
1177 }
1178 catch(WebAdmin::ConfigException& ex)
1179 {
1180 ErrLog(<<"Exception when starting WebAdmin: " << ex.getMessage());
1181 webAdminV6 = 0;
1182 }
1183
1184 if (!webAdminV6 || !webAdminV6->isSane())
1185 {
1186 CritLog(<<"Failed to start WebAdminV6");
1187 delete webAdminV6;
1188 cleanupObjects();
1189 return false;
1190 }
1191
1192 mWebAdminList.push_back(webAdminV6);
1193 }
1194 }
1195
1196 // This shouldn't happen because it would return false before
1197 // it reached this point
1198 if(!mWebAdminList.empty())
1199 {
1200 mWebAdminThread = new WebAdminThread(mWebAdminList);
1201 return true;
1202 }
1203 }
1204
1205 CritLog(<<"Failed to start any WebAdmin");
1206 return false;
1207 }
1208
1209 void
1210 ReproRunner::createRegSync()
1211 {
1212 assert(!mRegSyncClient);
1213 assert(!mRegSyncServerV4);
1214 assert(!mRegSyncServerV6);
1215 assert(!mRegSyncServerThread);
1216 if(mRegSyncPort != 0)
1217 {
1218 std::list<RegSyncServer*> regSyncServerList;
1219 if(mUseV4)
1220 {
1221 mRegSyncServerV4 = new RegSyncServer(dynamic_cast<InMemorySyncRegDb*>(mRegistrationPersistenceManager), mRegSyncPort, V4);
1222 regSyncServerList.push_back(mRegSyncServerV4);
1223 }
1224 if(mUseV6)
1225 {
1226 mRegSyncServerV6 = new RegSyncServer(dynamic_cast<InMemorySyncRegDb*>(mRegistrationPersistenceManager), mRegSyncPort, V6);
1227 regSyncServerList.push_back(mRegSyncServerV6);
1228 }
1229 if(!regSyncServerList.empty())
1230 {
1231 mRegSyncServerThread = new RegSyncServerThread(regSyncServerList);
1232 }
1233 Data regSyncPeerAddress(mProxyConfig->getConfigData("RegSyncPeer", ""));
1234 if(!regSyncPeerAddress.empty())
1235 {
1236 mRegSyncClient = new RegSyncClient(dynamic_cast<InMemorySyncRegDb*>(mRegistrationPersistenceManager), regSyncPeerAddress, mRegSyncPort);
1237 }
1238 }
1239 }
1240
1241 void
1242 ReproRunner::createCommandServer()
1243 {
1244 assert(mCommandServerList.empty());
1245 assert(!mCommandServerThread);
1246
1247 std::vector<resip::Data> commandServerBindAddresses;
1248 mProxyConfig->getConfigValue("CommandBindAddress", commandServerBindAddresses);
1249 int commandPort = mProxyConfig->getConfigInt("CommandPort", 5081);
1250
1251 if(commandPort != 0)
1252 {
1253 if(commandServerBindAddresses.empty())
1254 {
1255 if(mUseV4)
1256 {
1257 commandServerBindAddresses.push_back("0.0.0.0");
1258 }
1259 if(mUseV6)
1260 {
1261 commandServerBindAddresses.push_back("::");
1262 }
1263 }
1264
1265 for(std::vector<resip::Data>::iterator it = commandServerBindAddresses.begin(); it != commandServerBindAddresses.end(); it++)
1266 {
1267 if(mUseV4 && DnsUtil::isIpV4Address(*it))
1268 {
1269 CommandServer* pCommandServerV4 = new CommandServer(*this, *it, commandPort, V4);
1270
1271 if(pCommandServerV4->isSane())
1272 {
1273 mCommandServerList.push_back(pCommandServerV4);
1274 }
1275 else
1276 {
1277 CritLog(<<"Failed to start CommandServerV4");
1278 delete pCommandServerV4;
1279 }
1280 }
1281
1282 if(mUseV6 && DnsUtil::isIpV6Address(*it))
1283 {
1284 CommandServer* pCommandServerV6 = new CommandServer(*this, *it, commandPort, V6);
1285
1286 if(pCommandServerV6->isSane())
1287 {
1288 mCommandServerList.push_back(pCommandServerV6);
1289 }
1290 else
1291 {
1292 CritLog(<<"Failed to start CommandServerV6");
1293 delete pCommandServerV6;
1294 }
1295 }
1296 }
1297
1298 if(!mCommandServerList.empty())
1299 {
1300 mCommandServerThread = new CommandServerThread(mCommandServerList);
1301 }
1302 }
1303 }
1304
1305 Data
1306 ReproRunner::addDomains(TransactionUser& tu, bool log)
1307 {
1308 assert(mProxyConfig);
1309 Data realm;
1310
1311 std::vector<Data> configDomains;
1312 if(mProxyConfig->getConfigValue("Domains", configDomains))
1313 {
1314 for (std::vector<Data>::const_iterator i=configDomains.begin();
1315 i != configDomains.end(); ++i)
1316 {
1317 if(log) InfoLog (<< "Adding domain " << *i << " from command line");
1318 tu.addDomain(*i);
1319 if ( realm.empty() )
1320 {
1321 realm = *i;
1322 }
1323 }
1324 }
1325
1326 const ConfigStore::ConfigData& dList = mProxyConfig->getDataStore()->mConfigStore.getConfigs();
1327 for (ConfigStore::ConfigData::const_iterator i=dList.begin();
1328 i != dList.end(); ++i)
1329 {
1330 if(log) InfoLog (<< "Adding domain " << i->second.mDomain << " from config");
1331 tu.addDomain( i->second.mDomain );
1332 if ( realm.empty() )
1333 {
1334 realm = i->second.mDomain;
1335 }
1336 }
1337
1338 /* All of this logic has been commented out - the sysadmin must explicitly
1339 add any of the items below to the Domains config option in repro.config
1340
1341 Data localhostname(DnsUtil::getLocalHostName());
1342 if(log) InfoLog (<< "Adding local hostname domain " << localhostname );
1343 tu.addDomain(localhostname);
1344 if ( realm.empty() )
1345 {
1346 realm = localhostname;
1347 }
1348
1349 if(log) InfoLog (<< "Adding localhost domain.");
1350 tu.addDomain("localhost");
1351 if ( realm.empty() )
1352 {
1353 realm = "localhost";
1354 }
1355
1356 list<pair<Data,Data> > ips = DnsUtil::getInterfaces();
1357 for ( list<pair<Data,Data> >::const_iterator i=ips.begin(); i!=ips.end(); i++)
1358 {
1359 if(log) InfoLog( << "Adding domain for IP " << i->second << " from interface " << i->first );
1360 tu.addDomain(i->second);
1361 }
1362
1363 if(log) InfoLog (<< "Adding 127.0.0.1 domain.");
1364 tu.addDomain("127.0.0.1"); */
1365
1366 if( realm.empty() )
1367 {
1368 realm = "Unconfigured";
1369 }
1370
1371 return realm;
1372 }
1373
1374 bool
1375 ReproRunner::addTransports(bool& allTransportsSpecifyRecordRoute)
1376 {
1377 assert(mProxyConfig);
1378 assert(mSipStack);
1379
1380 allTransportsSpecifyRecordRoute=false;
1381 mStartupTransportRecordRoutes.clear();
1382
1383 bool useEmailAsSIP = mProxyConfig->getConfigBool("TLSUseEmailAsSIP", false);
1384 Data wsCookieAuthSharedSecret = mProxyConfig->getConfigData("WSCookieAuthSharedSecret", "");
1385 SharedPtr<BasicWsConnectionValidator> basicWsConnectionValidator; // NULL
1386 SharedPtr<WsCookieContextFactory> wsCookieContextFactory;
1387 if(!wsCookieAuthSharedSecret.empty())
1388 {
1389 basicWsConnectionValidator.reset(new BasicWsConnectionValidator(wsCookieAuthSharedSecret));
1390 Data infoCookieName = mProxyConfig->getConfigData("WSCookieNameInfo", "");
1391 Data extraCookieName = mProxyConfig->getConfigData("WSCookieNameExtra", "");
1392 Data macCookieName = mProxyConfig->getConfigData("WSCookieNameMac", "");
1393
1394 wsCookieContextFactory.reset(new BasicWsCookieContextFactory(infoCookieName, extraCookieName, macCookieName));
1395 }
1396
1397 try
1398 {
1399 // Check if advanced transport settings are provided
1400 std::set<Data> interfaceKeys;
1401 mProxyConfig->getConfigIndexKeys("Transport", interfaceKeys);
1402 DebugLog(<<"Found " << interfaceKeys.size() << " interface(s) defined in the advanced format");
1403 if(!interfaceKeys.empty())
1404 {
1405 // Sample config file format for advanced transport settings
1406 // Transport1Interface = 192.168.1.106:5061
1407 // Transport1Type = TLS
1408 // Transport1TlsDomain = sipdomain.com
1409 // Transport1TlsCertificate = /etc/ssl/crt/sipdomain.com.pem
1410 // Transport1TlsPrivateKey = /etc/ssl/private/sipdomain.com.pem
1411 // Transport1TlsPrivateKeyPassPhrase = <pwd>
1412 // Transport1TlsClientVerification = None
1413 // Transport1RecordRouteUri = sip:sipdomain.com;transport=TLS
1414 // Transport1RcvBufLen = 2000
1415
1416 allTransportsSpecifyRecordRoute = true;
1417
1418 const char *anchor;
1419 for(std::set<Data>::iterator it = interfaceKeys.begin();
1420 it != interfaceKeys.end();
1421 it++)
1422 {
1423 const Data& settingKeyBase = *it;
1424 DebugLog(<< "checking values for transport: " << settingKeyBase);
1425 Data interfaceSettingKey(settingKeyBase + "Interface");
1426 Data interfaceSettings = mProxyConfig->getConfigData(interfaceSettingKey, "", true);
1427 Data typeSettingKey(settingKeyBase + "Type");
1428 Data tlsDomainSettingKey(settingKeyBase + "TlsDomain");
1429 Data tlsCertificateSettingKey(settingKeyBase + "TlsCertificate");
1430 Data tlsPrivateKeySettingKey(settingKeyBase + "TlsPrivateKey");
1431 Data tlsPrivateKeyPassPhraseKey(settingKeyBase + "TlsPrivateKeyPassPhrase");
1432 Data tlsCVMSettingKey(settingKeyBase + "TlsClientVerification");
1433 Data recordRouteUriSettingKey(settingKeyBase + "RecordRouteUri");
1434 Data rcvBufSettingKey(settingKeyBase + "RcvBufLen");
1435
1436 // Parse out interface settings
1437 ParseBuffer pb(interfaceSettings);
1438 anchor = pb.position();
1439 pb.skipToEnd();
1440 pb.skipBackToChar(':'); // For IPv6 the last : should be the port
1441 pb.skipBackChar();
1442 if(!pb.eof())
1443 {
1444 Data ipAddr;
1445 Data portData;
1446 pb.data(ipAddr, anchor);
1447 pb.skipChar();
1448 anchor = pb.position();
1449 pb.skipToEnd();
1450 pb.data(portData, anchor);
1451 if(!DnsUtil::isIpAddress(ipAddr))
1452 {
1453 CritLog(<< "Malformed IP-address found in " << interfaceSettingKey << " setting: " << ipAddr);
1454 }
1455 int port = portData.convertInt();
1456 if(port == 0)
1457 {
1458 CritLog(<< "Invalid port found in " << interfaceSettingKey << " setting: " << port);
1459 }
1460 TransportType tt = Tuple::toTransport(mProxyConfig->getConfigData(typeSettingKey, "UDP"));
1461 if(tt == UNKNOWN_TRANSPORT)
1462 {
1463 CritLog(<< "Unknown transport type found in " << typeSettingKey << " setting: " << mProxyConfig->getConfigData(typeSettingKey, "UDP"));
1464 }
1465 Data tlsDomain = mProxyConfig->getConfigData(tlsDomainSettingKey, "");
1466 Data tlsCertificate = mProxyConfig->getConfigData(tlsCertificateSettingKey, "");
1467 Data tlsPrivateKey = mProxyConfig->getConfigData(tlsPrivateKeySettingKey, "");
1468 Data tlsPrivateKeyPassPhrase = mProxyConfig->getConfigData(tlsPrivateKeyPassPhraseKey, "");
1469 Data tlsCVMValue = mProxyConfig->getConfigData(tlsCVMSettingKey, "NONE");
1470 SecurityTypes::TlsClientVerificationMode cvm = SecurityTypes::None;
1471 if(isEqualNoCase(tlsCVMValue, "Optional"))
1472 {
1473 cvm = SecurityTypes::Optional;
1474 }
1475 else if(isEqualNoCase(tlsCVMValue, "Mandatory"))
1476 {
1477 cvm = SecurityTypes::Mandatory;
1478 }
1479 else if(!isEqualNoCase(tlsCVMValue, "None"))
1480 {
1481 CritLog(<< "Unknown TLS client verification mode found in " << tlsCVMSettingKey << " setting: " << tlsCVMValue);
1482 }
1483
1484 #ifdef USE_SSL
1485 // Make sure certificate material available before trying to instantiate Transport
1486 if(isSecure(tt))
1487 {
1488 Security* security = mSipStack->getSecurity();
1489 assert(security != 0);
1490 // FIXME: see comments about CertificatePath
1491 if(!tlsCertificate.empty())
1492 {
1493 security->addDomainCertPEM(tlsDomain, Data::fromFile(tlsCertificate));
1494 }
1495 if(!tlsPrivateKey.empty())
1496 {
1497 security->addDomainPrivateKeyPEM(tlsDomain, Data::fromFile(tlsPrivateKey), tlsPrivateKeyPassPhrase);
1498 }
1499 }
1500 #endif
1501
1502 Transport *t = mSipStack->addTransport(tt,
1503 port,
1504 DnsUtil::isIpV6Address(ipAddr) ? V6 : V4,
1505 StunEnabled,
1506 ipAddr, // interface to bind to
1507 tlsDomain,
1508 tlsPrivateKeyPassPhrase, // private key passphrase
1509 SecurityTypes::TLSv1, // sslType
1510 0, // transport flags
1511 tlsCertificate, tlsPrivateKey,
1512 cvm, // tls client verification mode
1513 useEmailAsSIP,
1514 basicWsConnectionValidator, wsCookieContextFactory);
1515
1516 if (t)
1517 {
1518 int rcvBufLen = mProxyConfig->getConfigInt(rcvBufSettingKey, 0);
1519 if (rcvBufLen >0 )
1520 {
1521 #if defined(RESIP_SIPSTACK_HAVE_FDPOLL)
1522 // this new method is part of the epoll changeset,
1523 // which isn't commited yet.
1524 t->setRcvBufLen(rcvBufLen);
1525 #else
1526 assert(0);
1527 #endif
1528 }
1529
1530 Data recordRouteUri = mProxyConfig->getConfigData(recordRouteUriSettingKey, "");
1531 if(!recordRouteUri.empty())
1532 {
1533 try
1534 {
1535 if(isEqualNoCase(recordRouteUri, "auto")) // auto generated record route uri
1536 {
1537 if(isSecure(tt))
1538 {
1539 NameAddr rr;
1540 rr.uri().host()=tlsDomain;
1541 rr.uri().port()=port;
1542 rr.uri().param(resip::p_transport)=resip::Tuple::toDataLower(tt);
1543 mStartupTransportRecordRoutes[t->getKey()] = rr; // Store to be added to Proxy after it is created
1544 InfoLog (<< "Transport specific record-route enabled (generated): " << rr);
1545 }
1546 else
1547 {
1548 NameAddr rr;
1549 rr.uri().host()=ipAddr;
1550 rr.uri().port()=port;
1551 rr.uri().param(resip::p_transport)=resip::Tuple::toDataLower(tt);
1552 mStartupTransportRecordRoutes[t->getKey()] = rr; // Store to be added to Proxy after it is created
1553 InfoLog (<< "Transport specific record-route enabled (generated): " << rr);
1554 }
1555 }
1556 else
1557 {
1558 NameAddr rr(recordRouteUri);
1559 mStartupTransportRecordRoutes[t->getKey()] = rr; // Store to be added to Proxy after it is created
1560 InfoLog (<< "Transport specific record-route enabled: " << rr);
1561 }
1562 }
1563 catch(BaseException& e)
1564 {
1565 ErrLog (<< "Invalid uri provided in " << recordRouteUriSettingKey << " setting (ignoring): " << e);
1566 allTransportsSpecifyRecordRoute = false;
1567 }
1568 }
1569 else
1570 {
1571 allTransportsSpecifyRecordRoute = false;
1572 }
1573 }
1574 }
1575 else
1576 {
1577 CritLog(<< "Port not specified in " << interfaceSettingKey << " setting: expected format is <IPAddress>:<Port>");
1578 return false;
1579 }
1580 }
1581 }
1582 else
1583 {
1584 int udpPort = mProxyConfig->getConfigInt("UDPPort", 5060);
1585 int tcpPort = mProxyConfig->getConfigInt("TCPPort", 5060);
1586 int tlsPort = mProxyConfig->getConfigInt("TLSPort", 5061);
1587 int wsPort = mProxyConfig->getConfigInt("WSPort", 80);
1588 int wssPort = mProxyConfig->getConfigInt("WSSPort", 443);
1589 int dtlsPort = mProxyConfig->getConfigInt("DTLSPort", 0);
1590 Data tlsDomain = mProxyConfig->getConfigData("TLSDomainName", "");
1591 Data tlsCertificate = mProxyConfig->getConfigData("TLSCertificate", "");
1592 Data tlsPrivateKey = mProxyConfig->getConfigData("TLSPrivateKey", "");
1593 Data tlsPrivateKeyPassPhrase = mProxyConfig->getConfigData("TlsPrivateKeyPassPhrase", "");
1594 Data tlsCVMValue = mProxyConfig->getConfigData("TLSClientVerification", "NONE");
1595 SecurityTypes::TlsClientVerificationMode cvm = SecurityTypes::None;
1596 if(isEqualNoCase(tlsCVMValue, "Optional"))
1597 {
1598 cvm = SecurityTypes::Optional;
1599 }
1600 else if(isEqualNoCase(tlsCVMValue, "Mandatory"))
1601 {
1602 cvm = SecurityTypes::Mandatory;
1603 }
1604 else if(!isEqualNoCase(tlsCVMValue, "None"))
1605 {
1606 CritLog(<< "Unknown TLS client verification mode found in TLSClientVerification setting: " << tlsCVMValue);
1607 }
1608
1609 #ifdef USE_SSL
1610 // Make sure certificate material available before trying to instantiate Transport
1611 if (tlsPort || wssPort || dtlsPort)
1612 {
1613 Security* security = mSipStack->getSecurity();
1614 assert(security != 0);
1615 // FIXME: should check that EITHER CertificatePath was set or both of these
1616 // are supplied
1617 // In any case, it will still give a helpful error when it fails to
1618 // create the transport
1619 if(!tlsCertificate.empty())
1620 {
1621 security->addDomainCertPEM(tlsDomain, Data::fromFile(tlsCertificate));
1622 }
1623 if(!tlsPrivateKey.empty())
1624 {
1625 security->addDomainPrivateKeyPEM(tlsDomain, Data::fromFile(tlsPrivateKey));
1626 }
1627 }
1628 #endif
1629
1630 if (udpPort)
1631 {
1632 if (mUseV4) mSipStack->addTransport(UDP, udpPort, V4, StunEnabled);
1633 if (mUseV6) mSipStack->addTransport(UDP, udpPort, V6, StunEnabled);
1634 }
1635 if (tcpPort)
1636 {
1637 if (mUseV4) mSipStack->addTransport(TCP, tcpPort, V4, StunEnabled);
1638 if (mUseV6) mSipStack->addTransport(TCP, tcpPort, V6, StunEnabled);
1639 }
1640 if (tlsPort)
1641 {
1642 if (mUseV4) mSipStack->addTransport(TLS, tlsPort, V4, StunEnabled, Data::Empty, tlsDomain, tlsPrivateKeyPassPhrase, SecurityTypes::TLSv1, 0, tlsCertificate, tlsPrivateKey, cvm, useEmailAsSIP);
1643 if (mUseV6) mSipStack->addTransport(TLS, tlsPort, V6, StunEnabled, Data::Empty, tlsDomain, tlsPrivateKeyPassPhrase, SecurityTypes::TLSv1, 0, tlsCertificate, tlsPrivateKey, cvm, useEmailAsSIP);
1644 }
1645 if (wsPort)
1646 {
1647 if (mUseV4) mSipStack->addTransport(WS, wsPort, V4, StunEnabled, Data::Empty, Data::Empty, Data::Empty, SecurityTypes::NoSSL, 0, "", "", SecurityTypes::None, false, basicWsConnectionValidator, wsCookieContextFactory);
1648 if (mUseV6) mSipStack->addTransport(WS, wsPort, V6, StunEnabled, Data::Empty, Data::Empty, Data::Empty, SecurityTypes::NoSSL, 0, "", "", SecurityTypes::None, false, basicWsConnectionValidator, wsCookieContextFactory);
1649 }
1650 if (wssPort)
1651 {
1652 if (mUseV4) mSipStack->addTransport(WSS, wssPort, V4, StunEnabled, Data::Empty, tlsDomain, tlsPrivateKeyPassPhrase, SecurityTypes::TLSv1, 0, tlsCertificate, tlsPrivateKey, cvm, useEmailAsSIP, basicWsConnectionValidator, wsCookieContextFactory);
1653 if (mUseV6) mSipStack->addTransport(WSS, wssPort, V6, StunEnabled, Data::Empty, tlsDomain, tlsPrivateKeyPassPhrase, SecurityTypes::TLSv1, 0, tlsCertificate, tlsPrivateKey, cvm, useEmailAsSIP, basicWsConnectionValidator, wsCookieContextFactory);
1654 }
1655 if (dtlsPort)
1656 {
1657 if (mUseV4) mSipStack->addTransport(DTLS, dtlsPort, V4, StunEnabled, Data::Empty, tlsDomain, tlsPrivateKeyPassPhrase, SecurityTypes::TLSv1, 0, tlsCertificate, tlsPrivateKey);
1658 if (mUseV6) mSipStack->addTransport(DTLS, dtlsPort, V6, StunEnabled, Data::Empty, tlsDomain, tlsPrivateKeyPassPhrase, SecurityTypes::TLSv1, 0, tlsCertificate, tlsPrivateKey);
1659 }
1660 }
1661 }
1662 catch (BaseException& e)
1663 {
1664 std::cerr << "Likely a port is already in use" << endl;
1665 InfoLog (<< "Caught: " << e);
1666 return false;
1667 }
1668 return true;
1669 }
1670
1671 void
1672 ReproRunner::addProcessor(repro::ProcessorChain& chain, std::auto_ptr<Processor> processor)
1673 {
1674 chain.addProcessor(processor);
1675 }
1676
1677 void // Monkeys
1678 ReproRunner::makeRequestProcessorChain(ProcessorChain& chain)
1679 {
1680 assert(mProxyConfig);
1681 assert(mRegistrationPersistenceManager);
1682
1683 // Add strict route fixup monkey
1684 addProcessor(chain, std::auto_ptr<Processor>(new StrictRouteFixup));
1685
1686 // Add is trusted node monkey
1687 addProcessor(chain, std::auto_ptr<Processor>(new IsTrustedNode(*mProxyConfig)));
1688
1689 // Add Certificate Authenticator - if required
1690 assert(mAuthFactory);
1691 if(mAuthFactory->certificateAuthEnabled())
1692 {
1693 // TODO: perhaps this should be initialised from the trusted node
1694 // monkey? Or should the list of trusted TLS peers be independent
1695 // from the trusted node list?
1696 // Should we used the same trustedPeers object that was
1697 // passed to TlsPeerAuthManager perhaps?
1698 addProcessor(chain, mAuthFactory->getCertificateAuthenticator());
1699 }
1700
1701 Data wsCookieAuthSharedSecret = mProxyConfig->getConfigData("WSCookieAuthSharedSecret", "");
1702 Data wsCookieExtraHeaderName = mProxyConfig->getConfigData("WSCookieExtraHeaderName", "X-WS-Session-Extra");
1703 if(!mAuthFactory->digestAuthEnabled() && !wsCookieAuthSharedSecret.empty())
1704 {
1705 addProcessor(chain, std::auto_ptr<Processor>(new CookieAuthenticator(wsCookieAuthSharedSecret, wsCookieExtraHeaderName, mSipStack)));
1706 }
1707
1708 // Add digest authenticator monkey - if required
1709 if (mAuthFactory->digestAuthEnabled())
1710 {
1711 addProcessor(chain, mAuthFactory->getDigestAuthenticator());
1712 }
1713
1714 // Add am I responsible monkey
1715 addProcessor(chain, std::auto_ptr<Processor>(new AmIResponsible));
1716
1717 // Add RequestFilter monkey
1718 if(!mProxyConfig->getConfigBool("DisableRequestFilterProcessor", false))
1719 {
1720 if(mAsyncProcessorDispatcher)
1721 {
1722 addProcessor(chain, std::auto_ptr<Processor>(new RequestFilter(*mProxyConfig, mAsyncProcessorDispatcher)));
1723 }
1724 else
1725 {
1726 WarningLog(<< "Could not start RequestFilter Processor due to no worker thread pool (NumAsyncProcessorWorkerThreads=0)");
1727 }
1728 }
1729
1730 // [TODO] support for GRUU is on roadmap. When it is added the GruuMonkey will go here
1731
1732 // [TODO] support for Manipulating Tel URIs is on the roadmap.
1733 // When added, the telUriMonkey will go here
1734
1735 std::vector<Data> routeSet;
1736 mProxyConfig->getConfigValue("Routes", routeSet);
1737 if (routeSet.empty())
1738 {
1739 // add static route monkey
1740 addProcessor(chain, std::auto_ptr<Processor>(new StaticRoute(*mProxyConfig)));
1741 }
1742 else
1743 {
1744 // add simple static route monkey
1745 addProcessor(chain, std::auto_ptr<Processor>(new SimpleStaticRoute(*mProxyConfig)));
1746 }
1747
1748 // Add location server monkey
1749 addProcessor(chain, std::auto_ptr<Processor>(new LocationServer(*mProxyConfig, *mRegistrationPersistenceManager, mAuthFactory->getDispatcher())));
1750
1751 // Add message silo monkey
1752 if(mProxyConfig->getConfigBool("MessageSiloEnabled", false))
1753 {
1754 if(mAsyncProcessorDispatcher && mRegistrar)
1755 {
1756 MessageSilo* silo = new MessageSilo(*mProxyConfig, mAsyncProcessorDispatcher);
1757 mRegistrar->addRegistrarHandler(silo);
1758 addProcessor(chain, std::auto_ptr<Processor>(silo));
1759 }
1760 else
1761 {
1762 WarningLog(<< "Could not start MessageSilo Processor due to no worker thread pool (NumAsyncProcessorWorkerThreads=0) or Registrar");
1763 }
1764 }
1765 }
1766
1767 void // Lemurs
1768 ReproRunner::makeResponseProcessorChain(ProcessorChain& chain)
1769 {
1770 assert(mProxyConfig);
1771 assert(mRegistrationPersistenceManager);
1772
1773 // Add outbound target handler lemur
1774 addProcessor(chain, std::auto_ptr<Processor>(new OutboundTargetHandler(*mRegistrationPersistenceManager)));
1775
1776 if (mProxyConfig->getConfigBool("RecursiveRedirect", false))
1777 {
1778 // Add recursive redirect lemur
1779 addProcessor(chain, std::auto_ptr<Processor>(new RecursiveRedirect));
1780 }
1781 }
1782
1783 void // Baboons
1784 ReproRunner::makeTargetProcessorChain(ProcessorChain& chain)
1785 {
1786 assert(mProxyConfig);
1787
1788 #ifndef RESIP_FIXED_POINT
1789 if(mProxyConfig->getConfigBool("GeoProximityTargetSorting", false))
1790 {
1791 addProcessor(chain, std::auto_ptr<Processor>(new GeoProximityTargetSorter(*mProxyConfig)));
1792 }
1793 #endif
1794
1795 if(mProxyConfig->getConfigBool("QValue", true))
1796 {
1797 // Add q value target handler baboon
1798 addProcessor(chain, std::auto_ptr<Processor>(new QValueTargetHandler(*mProxyConfig)));
1799 }
1800
1801 // Add simple target handler baboon
1802 addProcessor(chain, std::auto_ptr<Processor>(new SimpleTargetHandler));
1803 }
1804
1805 bool
1806 ReproRunner::operator()(resip::StatisticsMessage &statsMessage)
1807 {
1808 // Dispatch to each command server
1809 for(std::list<CommandServer*>::iterator it = mCommandServerList.begin(); it != mCommandServerList.end(); it++)
1810 {
1811 (*it)->handleStatisticsMessage(statsMessage);
1812 }
1813 return true;
1814 }
1815
1816 /* ====================================================================
1817 * The Vovida Software License, Version 1.0
1818 *
1819 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
1820 *
1821 * Redistribution and use in source and binary forms, with or without
1822 * modification, are permitted provided that the following conditions
1823 * are met:
1824 *
1825 * 1. Redistributions of source code must retain the above copyright
1826 * notice, this list of conditions and the following disclaimer.
1827 *
1828 * 2. Redistributions in binary form must reproduce the above copyright
1829 * notice, this list of conditions and the following disclaimer in
1830 * the documentation and/or other materials provided with the
1831 * distribution.
1832 *
1833 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1834 * and "Vovida Open Communication Application Library (VOCAL)" must
1835 * not be used to endorse or promote products derived from this
1836 * software without prior written permission. For written
1837 * permission, please contact vocal@vovida.org.
1838 *
1839 * 4. Products derived from this software may not be called "VOCAL", nor
1840 * may "VOCAL" appear in their name, without prior written
1841 * permission of Vovida Networks, Inc.
1842 *
1843 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1844 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1845 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1846 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
1847 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1848 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1849 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1850 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1851 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1852 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1853 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1854 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1855 * DAMAGE.
1856 *
1857 * ====================================================================
1858 */

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27