~ubuntu-branches/ubuntu/saucy/resiprocate/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/0003-log-an-error-if-TLS-mappings-file-missing.patch/repro/ReproRunner.cxx

  • Committer: Package Import Robot
  • Author(s): Daniel Pocock
  • Date: 2013-03-21 20:12:33 UTC
  • Revision ID: package-import@ubuntu.com-20130321201233-xw981446hds8c2t7
Tags: 1.8.5-3
log an error if TLS mappings file missing (Closes: #703644)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#if defined(HAVE_CONFIG_H)
 
2
#include "config.h"
 
3
#endif
 
4
 
 
5
#include <iostream>
 
6
#include <fstream>
 
7
#include <stdexcept>
 
8
 
 
9
#include "rutil/Log.hxx"
 
10
#include "rutil/Logger.hxx"
 
11
#include "rutil/DnsUtil.hxx"
 
12
#include "rutil/dns/DnsStub.hxx"
 
13
#include "rutil/GeneralCongestionManager.hxx"
 
14
 
 
15
#include "resip/stack/SipStack.hxx"
 
16
#include "resip/stack/Compression.hxx"
 
17
#include "resip/stack/EventStackThread.hxx"
 
18
#include "resip/stack/InteropHelper.hxx"
 
19
#include "resip/stack/ConnectionManager.hxx"
 
20
 
 
21
#include "resip/dum/InMemorySyncRegDb.hxx"
 
22
#include "resip/dum/MasterProfile.hxx"
 
23
#include "resip/dum/DialogUsageManager.hxx"
 
24
#include "resip/dum/DumThread.hxx"
 
25
#include "resip/dum/TlsPeerAuthManager.hxx"
 
26
 
 
27
#include "repro/AsyncProcessorWorker.hxx"
 
28
#include "repro/ReproRunner.hxx"
 
29
#include "repro/Proxy.hxx"
 
30
#include "repro/ProxyConfig.hxx"
 
31
#include "repro/BerkeleyDb.hxx"
 
32
#include "repro/Dispatcher.hxx"
 
33
#include "repro/UserAuthGrabber.hxx"
 
34
#include "repro/ProcessorChain.hxx"
 
35
#include "repro/ReproVersion.hxx"
 
36
#include "repro/WebAdmin.hxx"
 
37
#include "repro/WebAdminThread.hxx"
 
38
#include "repro/Registrar.hxx"
 
39
#include "repro/ReproServerAuthManager.hxx"
 
40
#include "repro/RegSyncClient.hxx"
 
41
#include "repro/RegSyncServer.hxx"
 
42
#include "repro/RegSyncServerThread.hxx"
 
43
#include "repro/CommandServer.hxx"
 
44
#include "repro/CommandServerThread.hxx"
 
45
#include "repro/monkeys/IsTrustedNode.hxx"
 
46
#include "repro/monkeys/AmIResponsible.hxx"
 
47
#include "repro/monkeys/DigestAuthenticator.hxx"
 
48
#include "repro/monkeys/LocationServer.hxx"
 
49
#include "repro/monkeys/RecursiveRedirect.hxx"
 
50
#include "repro/monkeys/SimpleStaticRoute.hxx"
 
51
#include "repro/monkeys/StaticRoute.hxx"
 
52
#include "repro/monkeys/StrictRouteFixup.hxx"
 
53
#include "repro/monkeys/OutboundTargetHandler.hxx"
 
54
#include "repro/monkeys/QValueTargetHandler.hxx"
 
55
#include "repro/monkeys/SimpleTargetHandler.hxx"
 
56
#include "repro/monkeys/GeoProximityTargetSorter.hxx"
 
57
#include "repro/monkeys/RequestFilter.hxx"
 
58
#include "repro/monkeys/MessageSilo.hxx"
 
59
#include "repro/monkeys/CertificateAuthenticator.hxx"
 
60
 
 
61
#if defined(USE_SSL)
 
62
#include "repro/stateAgents/CertServer.hxx"
 
63
#include "resip/stack/ssl/Security.hxx"
 
64
#endif
 
65
 
 
66
#if defined(USE_MYSQL)
 
67
#include "repro/MySqlDb.hxx"
 
68
#endif
 
69
 
 
70
#include "rutil/WinLeakCheck.hxx"
 
71
 
 
72
#define RESIPROCATE_SUBSYSTEM resip::Subsystem::REPRO
 
73
 
 
74
using namespace resip;
 
75
using namespace repro;
 
76
using namespace std;
 
77
 
 
78
class ReproLogger : public ExternalLogger
 
79
{
 
80
public:
 
81
   virtual ~ReproLogger() {}
 
82
   /** return true to also do default logging, false to supress default logging. */
 
83
   virtual bool operator()(Log::Level level,
 
84
                           const Subsystem& subsystem, 
 
85
                           const Data& appName,
 
86
                           const char* file,
 
87
                           int line,
 
88
                           const Data& message,
 
89
                           const Data& messageWithHeaders)
 
90
   {
 
91
      // Log any errors to the screen 
 
92
      if(level <= Log::Err)
 
93
      {
 
94
         resipCout << messageWithHeaders << endl;
 
95
      }
 
96
      return true;
 
97
   }
 
98
};
 
99
ReproLogger g_ReproLogger;
 
100
 
 
101
ReproRunner::ReproRunner()
 
102
   : mRunning(false)
 
103
   , mRestarting(false)
 
104
   , mThreadedStack(false)
 
105
   , mSipAuthDisabled(false)
 
106
   , mUseV4(true)
 
107
   , mUseV6 (false)
 
108
   , mRegSyncPort(0)
 
109
   , mProxyConfig(0)
 
110
   , mFdPollGrp(0)
 
111
   , mAsyncProcessHandler(0)
 
112
   , mSipStack(0)
 
113
   , mStackThread(0)
 
114
   , mAbstractDb(0)
 
115
   , mRuntimeAbstractDb(0)
 
116
   , mRegistrationPersistenceManager(0)
 
117
   , mAuthRequestDispatcher(0)
 
118
   , mAsyncProcessorDispatcher(0)
 
119
   , mMonkeys(0)
 
120
   , mLemurs(0)
 
121
   , mBaboons(0)
 
122
   , mProxy(0)
 
123
   , mWebAdmin(0)
 
124
   , mWebAdminThread(0)
 
125
   , mRegistrar(0)
 
126
   , mDum(0)
 
127
   , mDumThread(0)
 
128
   , mCertServer(0)
 
129
   , mRegSyncClient(0)
 
130
   , mRegSyncServerV4(0)
 
131
   , mRegSyncServerV6(0)
 
132
   , mRegSyncServerThread(0)
 
133
   , mCommandServerV4(0)
 
134
   , mCommandServerV6(0)
 
135
   , mCommandServerThread(0)
 
136
   , mCongestionManager(0)
 
137
{
 
138
}
 
139
 
 
140
ReproRunner::~ReproRunner()
 
141
{
 
142
   if(mRunning) shutdown();
 
143
}
 
144
 
 
145
bool
 
146
ReproRunner::run(int argc, char** argv)
 
147
{
 
148
   if(mRunning) return false;
 
149
 
 
150
   if(!mRestarting)
 
151
   {
 
152
      // Store original arc and argv - so we can reuse them on restart request
 
153
      mArgc = argc;
 
154
      mArgv = argv;
 
155
   }
 
156
 
 
157
   // Parse command line and configuration file
 
158
   assert(!mProxyConfig);
 
159
   Data defaultConfigFilename("repro.config");
 
160
   try
 
161
   {
 
162
      mProxyConfig = new ProxyConfig();
 
163
      mProxyConfig->parseConfig(mArgc, mArgv, defaultConfigFilename);
 
164
   }
 
165
   catch(BaseException& ex)
 
166
   {
 
167
      std::cerr << "Error parsing configuration: " << ex << std::endl;
 
168
      return false;
 
169
   }
 
170
 
 
171
   // Non-Windows server process stuff
 
172
   if(!mRestarting)
 
173
   {
 
174
      setPidFile(mProxyConfig->getConfigData("PidFile", "", true));
 
175
      if(mProxyConfig->getConfigBool("Daemonize", false))
 
176
      {
 
177
         daemonize();
 
178
      }
 
179
   }
 
180
 
 
181
   // Initialize resip logger
 
182
   GenericLogImpl::MaxByteCount = mProxyConfig->getConfigUnsignedLong("LogFileMaxBytes", 5242880 /*5 Mb */);
 
183
   Data loggingType = mProxyConfig->getConfigData("LoggingType", "cout", true);
 
184
   Log::initialize(loggingType, 
 
185
                   mProxyConfig->getConfigData("LogLevel", "INFO", true), 
 
186
                   mArgv[0], 
 
187
                   mProxyConfig->getConfigData("LogFilename", "repro.log", true).c_str(),
 
188
                   isEqualNoCase(loggingType, "file") ? &g_ReproLogger : 0); // if logging to file then write WARNINGS, and Errors to console still
 
189
 
 
190
   InfoLog( << "Starting repro version " << VersionUtils::instance().releaseVersion() << "...");
 
191
 
 
192
   // Create SipStack and associated objects
 
193
   if(!createSipStack())
 
194
   {
 
195
      return false;
 
196
   }
 
197
 
 
198
   // Create datastore
 
199
   if(!createDatastore())
 
200
   {
 
201
      return false;
 
202
   }
 
203
 
 
204
   // Create DialogUsageManager that handles ServerRegistration,
 
205
   // and potentially certificate subscription server
 
206
   createDialogUsageManager();
 
207
 
 
208
   // Create the Proxy and associate objects
 
209
   if(!createProxy())
 
210
   {
 
211
      return false;
 
212
   }
 
213
 
 
214
   // Create HTTP WebAdmin and Thread
 
215
   if(!createWebAdmin())
 
216
   {
 
217
      return false;
 
218
   }
 
219
 
 
220
   // Create reg sync components if required
 
221
   createRegSync();
 
222
 
 
223
   // Create command server if required
 
224
   if(!mRestarting)
 
225
   {
 
226
      createCommandServer();
 
227
   }
 
228
 
 
229
   // Make it all go - startup all threads
 
230
   mThreadedStack = mProxyConfig->getConfigBool("ThreadedStack", true);
 
231
   if(mThreadedStack)
 
232
   {
 
233
      // If configured, then start the sub-threads within the stack
 
234
      mSipStack->run();
 
235
   }
 
236
   mStackThread->run();
 
237
   if(mDumThread)
 
238
   {
 
239
      mDumThread->run();
 
240
   }
 
241
   mProxy->run();
 
242
   if(mWebAdminThread)
 
243
   {
 
244
      mWebAdminThread->run();
 
245
   }
 
246
   if(!mRestarting && mCommandServerThread)
 
247
   {
 
248
      mCommandServerThread->run();
 
249
   }
 
250
   if(mRegSyncServerThread)
 
251
   {
 
252
      mRegSyncServerThread->run();
 
253
   }
 
254
   if(mRegSyncClient)
 
255
   {
 
256
      mRegSyncClient->run();
 
257
   }
 
258
 
 
259
   mRunning = true;
 
260
 
 
261
   return true;
 
262
}
 
263
 
 
264
void 
 
265
ReproRunner::shutdown()
 
266
{
 
267
   if(!mRunning) return;
 
268
 
 
269
   // Tell all threads to shutdown
 
270
   if(mWebAdminThread)
 
271
   {
 
272
      mWebAdminThread->shutdown();
 
273
   }
 
274
   if(mDumThread)
 
275
   {
 
276
      mDumThread->shutdown();
 
277
   }
 
278
   mProxy->shutdown();
 
279
   mStackThread->shutdown();
 
280
   if(!mRestarting && mCommandServerThread)  // leave command server running if we are restarting
 
281
   {
 
282
      mCommandServerThread->shutdown();
 
283
   }
 
284
   if(mRegSyncServerThread)
 
285
   {
 
286
      mRegSyncServerThread->shutdown();
 
287
   }
 
288
   if(mRegSyncClient)
 
289
   {
 
290
      mRegSyncClient->shutdown();
 
291
   }
 
292
 
 
293
   // Wait for all threads to shutdown, and destroy objects
 
294
   mProxy->join();
 
295
   if(mThreadedStack)
 
296
   {
 
297
      mSipStack->shutdownAndJoinThreads();
 
298
   }
 
299
   mStackThread->join();
 
300
   if(mWebAdminThread) 
 
301
   {
 
302
      mWebAdminThread->join();
 
303
   }
 
304
   if(mDumThread)
 
305
   {
 
306
      mDumThread->join();
 
307
   }
 
308
   if(mAuthRequestDispatcher)
 
309
   {
 
310
      // Both proxy and dum threads are down at this point, we can 
 
311
      // destroy the authRequest dispatcher and associated threads now
 
312
      delete mAuthRequestDispatcher;
 
313
      mAuthRequestDispatcher = 0;
 
314
   }
 
315
   if(mAsyncProcessorDispatcher)
 
316
   {
 
317
      // Both proxy and dum threads are down at this point, we can 
 
318
      // destroy the async processor dispatcher and associated threads now
 
319
      delete mAsyncProcessorDispatcher;
 
320
      mAsyncProcessorDispatcher = 0;
 
321
   }
 
322
   if(!mRestarting && mCommandServerThread)  // we leave command server running during restart
 
323
   {
 
324
      mCommandServerThread->join();
 
325
   }
 
326
   if(mRegSyncServerThread)
 
327
   {
 
328
      mRegSyncServerThread->join();
 
329
   }
 
330
   if(mRegSyncClient)
 
331
   {
 
332
      mRegSyncClient->join();
 
333
   }
 
334
 
 
335
   mSipStack->setCongestionManager(0);
 
336
 
 
337
   cleanupObjects();
 
338
   mRunning = false;
 
339
}
 
340
 
 
341
void
 
342
ReproRunner::restart()
 
343
{
 
344
   if(!mRunning) return;
 
345
   mRestarting = true;
 
346
   shutdown();
 
347
   run(0, 0);
 
348
   mRestarting = false;
 
349
}
 
350
 
 
351
void
 
352
ReproRunner::cleanupObjects()
 
353
{
 
354
   delete mCongestionManager; mCongestionManager = 0;
 
355
   if(!mRestarting)
 
356
   {
 
357
      // We leave command server running during restart
 
358
      delete mCommandServerThread; mCommandServerThread = 0;
 
359
      delete mCommandServerV6; mCommandServerV6 = 0;
 
360
      delete mCommandServerV4; mCommandServerV4 = 0;
 
361
   }
 
362
   delete mRegSyncServerThread; mRegSyncServerThread = 0;
 
363
   delete mRegSyncServerV6; mRegSyncServerV6 = 0;
 
364
   delete mRegSyncServerV4; mRegSyncServerV4 = 0;
 
365
   delete mRegSyncClient; mRegSyncClient = 0;
 
366
#if defined(USE_SSL)
 
367
   delete mCertServer; mCertServer = 0;
 
368
#endif
 
369
   delete mDumThread; mDumThread = 0;
 
370
   delete mDum; mDum = 0;
 
371
   delete mRegistrar; mRegistrar = 0;
 
372
   delete mWebAdminThread; mWebAdminThread = 0;
 
373
   delete mWebAdmin; mWebAdmin = 0;
 
374
   delete mProxy; mProxy = 0;
 
375
   delete mBaboons; mBaboons = 0;
 
376
   delete mLemurs; mLemurs = 0;
 
377
   delete mMonkeys; mMonkeys = 0;
 
378
   delete mAuthRequestDispatcher; mAuthRequestDispatcher = 0;
 
379
   delete mAsyncProcessorDispatcher; mAsyncProcessorDispatcher = 0;
 
380
   if(!mRestarting) 
 
381
   {
 
382
      // If we are restarting then leave the In Memory Registration database intact
 
383
      delete mRegistrationPersistenceManager; mRegistrationPersistenceManager = 0;
 
384
   }
 
385
   delete mAbstractDb; mAbstractDb = 0;
 
386
   delete mRuntimeAbstractDb; mRuntimeAbstractDb = 0;
 
387
   delete mStackThread; mStackThread = 0;
 
388
   delete mSipStack; mSipStack = 0;
 
389
   delete mAsyncProcessHandler; mAsyncProcessHandler = 0;
 
390
   delete mFdPollGrp; mFdPollGrp = 0;
 
391
   delete mProxyConfig; mProxyConfig = 0;
 
392
}
 
393
 
 
394
bool
 
395
ReproRunner::createSipStack()
 
396
{
 
397
   // Override T1 timer if configured to do so
 
398
   unsigned long overrideT1 = mProxyConfig->getConfigInt("TimerT1", 0);
 
399
   if(overrideT1)
 
400
   {
 
401
      WarningLog(<< "Overriding T1! (new value is " << 
 
402
               overrideT1 << ")");
 
403
      resip::Timer::resetT1(overrideT1);
 
404
   }
 
405
 
 
406
   // Create Security (TLS / Certificates) and Compression (SigComp) objects if
 
407
   // pre-precessor defines are enabled
 
408
   Security* security = 0;
 
409
   Compression* compression = 0;
 
410
#ifdef USE_SSL
 
411
#ifdef WIN32
 
412
   Data certPath("C:\\sipCerts");
 
413
#else 
 
414
   Data certPath(getenv("HOME"));
 
415
   certPath += "/.sipCerts";
 
416
#endif
 
417
   mProxyConfig->getConfigValue("CertificatePath", certPath);
 
418
   security = new Security(certPath);
 
419
   Data caDir;
 
420
   mProxyConfig->getConfigValue("CADirectory", caDir);
 
421
   if(!caDir.empty())
 
422
   {
 
423
      security->addCADirectory(caDir);
 
424
   }
 
425
   Data caFile;
 
426
   mProxyConfig->getConfigValue("CAFile", caFile);
 
427
   if(!caFile.empty())
 
428
   {
 
429
      security->addCAFile(caFile);
 
430
   }
 
431
#endif
 
432
 
 
433
#ifdef USE_SIGCOMP
 
434
   compression = new Compression(Compression::DEFLATE);
 
435
#endif
 
436
 
 
437
   // Create EventThreadInterruptor used to wake up the stack for 
 
438
   // for reasons other than an Fd signalling
 
439
   assert(!mFdPollGrp);
 
440
   mFdPollGrp = FdPollGrp::create();
 
441
   assert(!mAsyncProcessHandler);
 
442
   mAsyncProcessHandler = new EventThreadInterruptor(*mFdPollGrp);
 
443
 
 
444
   // Set Flags that will enable/disable IPv4 and/or IPv6, based on 
 
445
   // configuration and pre-processor flags
 
446
   mUseV4 = !mProxyConfig->getConfigBool("DisableIPv4", false);
 
447
#ifdef USE_IPV6
 
448
   mUseV6 = mProxyConfig->getConfigBool("EnableIPv6", true);
 
449
#else
 
450
   bool useV6 = false;
 
451
#endif
 
452
   if (mUseV4) InfoLog (<< "V4 enabled");
 
453
   if (mUseV6) InfoLog (<< "V6 enabled");
 
454
 
 
455
   // Build DNS Server list from config
 
456
   DnsStub::NameserverList dnsServers;
 
457
   std::vector<resip::Data> dnsServersConfig;
 
458
   mProxyConfig->getConfigValue("DNSServers", dnsServersConfig);
 
459
   for(std::vector<resip::Data>::iterator it = dnsServersConfig.begin(); it != dnsServersConfig.end(); it++)
 
460
   {
 
461
      if((mUseV4 && DnsUtil::isIpV4Address(*it)) || (mUseV6 && DnsUtil::isIpV6Address(*it)))
 
462
      {
 
463
         InfoLog(<< "Using DNS Server from config: " << *it);
 
464
         dnsServers.push_back(Tuple(*it, 0, UNKNOWN_TRANSPORT).toGenericIPAddress());
 
465
      }
 
466
   }
 
467
 
 
468
   // Create the SipStack Object
 
469
   assert(!mSipStack);
 
470
   mSipStack = new SipStack(security,
 
471
                            dnsServers,
 
472
                            mAsyncProcessHandler,
 
473
                            /*stateless*/false,
 
474
                            /*socketFunc*/0,
 
475
                            compression,
 
476
                            mFdPollGrp);
 
477
 
 
478
   // Set any enum suffixes from configuration
 
479
   std::vector<Data> enumSuffixes;
 
480
   mProxyConfig->getConfigValue("EnumSuffixes", enumSuffixes);
 
481
   if (enumSuffixes.size() > 0)
 
482
   {
 
483
      mSipStack->setEnumSuffixes(enumSuffixes);
 
484
   }
 
485
 
 
486
   // Set any enum domains from configuration
 
487
   std::map<Data,Data> enumDomains;
 
488
   std::vector<Data> _enumDomains;
 
489
   mProxyConfig->getConfigValue("EnumDomains", _enumDomains);
 
490
   if (enumSuffixes.size() > 0)
 
491
   {
 
492
      for(std::vector<Data>::iterator it = _enumDomains.begin(); it != _enumDomains.end(); it++)
 
493
      {
 
494
         enumDomains[*it] = *it;
 
495
      }
 
496
      mSipStack->setEnumDomains(enumDomains);
 
497
   }
 
498
 
 
499
   // Add stack transports
 
500
   bool allTransportsSpecifyRecordRoute=false;
 
501
   if(!addTransports(allTransportsSpecifyRecordRoute))
 
502
   {
 
503
      cleanupObjects();
 
504
      return false;
 
505
   }
 
506
 
 
507
   // Enable and configure RFC5626 Outbound support
 
508
   InteropHelper::setOutboundVersion(mProxyConfig->getConfigInt("OutboundVersion", 5626));
 
509
   InteropHelper::setOutboundSupported(mProxyConfig->getConfigBool("DisableOutbound", false) ? false : true);
 
510
   InteropHelper::setRRTokenHackEnabled(mProxyConfig->getConfigBool("EnableFlowTokens", false));
 
511
   InteropHelper::setAssumeFirstHopSupportsOutboundEnabled(mProxyConfig->getConfigBool("AssumeFirstHopSupportsOutbound", false));
 
512
   Data clientNATDetectionMode = mProxyConfig->getConfigData("ClientNatDetectionMode", "DISABLED");
 
513
   if(isEqualNoCase(clientNATDetectionMode, "ENABLED"))
 
514
   {
 
515
      InteropHelper::setClientNATDetectionMode(InteropHelper::ClientNATDetectionEnabled);
 
516
   }
 
517
   else if(isEqualNoCase(clientNATDetectionMode, "PRIVATE_TO_PUBLIC"))
 
518
   {
 
519
      InteropHelper::setClientNATDetectionMode(InteropHelper::ClientNATDetectionPrivateToPublicOnly);
 
520
   }
 
521
   unsigned long outboundFlowTimer = mProxyConfig->getConfigUnsignedLong("FlowTimer", 0);
 
522
   if(outboundFlowTimer > 0)
 
523
   {
 
524
      InteropHelper::setFlowTimerSeconds(outboundFlowTimer);
 
525
      ConnectionManager::MinimumGcAge = 7200000; // Timeout connections not related to a flow timer after 2 hours - TODO make configurable
 
526
      ConnectionManager::EnableAgressiveGc = true;
 
527
   }
 
528
 
 
529
   // Check Path and RecordRoute settings, print warning if features are enabled that
 
530
   // require record-routing and record-route uri(s) is not configured
 
531
   bool assumePath = mProxyConfig->getConfigBool("AssumePath", false);
 
532
   bool forceRecordRoute = mProxyConfig->getConfigBool("ForceRecordRouting", false);
 
533
   Uri recordRouteUri;
 
534
   mProxyConfig->getConfigValue("RecordRouteUri", recordRouteUri);
 
535
   if((InteropHelper::getOutboundSupported() 
 
536
         || InteropHelper::getRRTokenHackEnabled()
 
537
         || InteropHelper::getClientNATDetectionMode() != InteropHelper::ClientNATDetectionDisabled
 
538
         || assumePath
 
539
         || forceRecordRoute
 
540
      )
 
541
      && !(allTransportsSpecifyRecordRoute || !recordRouteUri.host().empty()))
 
542
   {
 
543
      CritLog(<< "In order for outbound support, the Record-Route flow-token"
 
544
      " hack, or force-record-route to work, you MUST specify a Record-Route URI. Launching "
 
545
      "without...");
 
546
      InteropHelper::setOutboundSupported(false);
 
547
      InteropHelper::setRRTokenHackEnabled(false);
 
548
      InteropHelper::setClientNATDetectionMode(InteropHelper::ClientNATDetectionDisabled);
 
549
      assumePath = false;
 
550
      forceRecordRoute=false;
 
551
   }
 
552
 
 
553
   // Configure misc. stack settings
 
554
   mSipStack->setFixBadDialogIdentifiers(false);
 
555
   mSipStack->setFixBadCSeqNumbers(false);
 
556
   int statsLogInterval = mProxyConfig->getConfigInt("StatisticsLogInterval", 60);
 
557
   if(statsLogInterval > 0)
 
558
   {
 
559
      mSipStack->setStatisticsInterval(statsLogInterval);
 
560
      mSipStack->statisticsManagerEnabled() = true;
 
561
   }
 
562
   else
 
563
   {
 
564
      mSipStack->statisticsManagerEnabled() = false;
 
565
   }
 
566
 
 
567
   // Create Congestion Manager, if required
 
568
   assert(!mCongestionManager);
 
569
   if(mProxyConfig->getConfigBool("CongestionManagement", true))
 
570
   {
 
571
      Data metricData = mProxyConfig->getConfigData("CongestionManagementMetric", "WAIT_TIME", true);
 
572
      GeneralCongestionManager::MetricType metric = GeneralCongestionManager::WAIT_TIME;
 
573
      if(isEqualNoCase(metricData, "TIME_DEPTH"))
 
574
      {
 
575
         metric = GeneralCongestionManager::TIME_DEPTH;
 
576
      }
 
577
      else if(isEqualNoCase(metricData, "SIZE"))
 
578
      {
 
579
         metric = GeneralCongestionManager::SIZE;
 
580
      }
 
581
      else if(!isEqualNoCase(metricData, "WAIT_TIME"))
 
582
      {
 
583
         WarningLog( << "CongestionManagementMetric specified as an unknown value (" << metricData << "), defaulting to WAIT_TIME.");
 
584
      }
 
585
      mCongestionManager = new GeneralCongestionManager(
 
586
                                          metric, 
 
587
                                          mProxyConfig->getConfigUnsignedLong("CongestionManagementTolerance", 200));
 
588
      mSipStack->setCongestionManager(mCongestionManager);
 
589
   }
 
590
 
 
591
   // Create base thread to run stack in (note:  stack may use other sub-threads, depending on configuration)
 
592
   assert(!mStackThread);
 
593
   mStackThread = new EventStackThread(*mSipStack,
 
594
                                       *dynamic_cast<EventThreadInterruptor*>(mAsyncProcessHandler),
 
595
                                       *mFdPollGrp);
 
596
   return true;
 
597
}
 
598
 
 
599
bool 
 
600
ReproRunner::createDatastore()
 
601
{
 
602
   // Create Database access objects
 
603
   assert(!mAbstractDb);
 
604
   assert(!mRuntimeAbstractDb);
 
605
#ifdef USE_MYSQL
 
606
   Data mySQLServer;
 
607
   mProxyConfig->getConfigValue("MySQLServer", mySQLServer);
 
608
   if(!mySQLServer.empty())
 
609
   {
 
610
      mAbstractDb = new MySqlDb(mySQLServer, 
 
611
                       mProxyConfig->getConfigData("MySQLUser", ""), 
 
612
                       mProxyConfig->getConfigData("MySQLPassword", ""),
 
613
                       mProxyConfig->getConfigData("MySQLDatabaseName", ""),
 
614
                       mProxyConfig->getConfigUnsignedLong("MySQLPort", 0),
 
615
                       mProxyConfig->getConfigData("MySQLCustomUserAuthQuery", ""));
 
616
   }
 
617
   Data runtimeMySQLServer;
 
618
   mProxyConfig->getConfigValue("RuntimeMySQLServer", runtimeMySQLServer);
 
619
   if(!runtimeMySQLServer.empty())
 
620
   {
 
621
      mRuntimeAbstractDb = new MySqlDb(runtimeMySQLServer,
 
622
                       mProxyConfig->getConfigData("RuntimeMySQLUser", ""), 
 
623
                       mProxyConfig->getConfigData("RuntimeMySQLPassword", ""),
 
624
                       mProxyConfig->getConfigData("RuntimeMySQLDatabaseName", ""),
 
625
                       mProxyConfig->getConfigUnsignedLong("RuntimeMySQLPort", 0),
 
626
                       mProxyConfig->getConfigData("MySQLCustomUserAuthQuery", ""));
 
627
   }
 
628
#endif
 
629
   if (!mAbstractDb)
 
630
   {
 
631
      mAbstractDb = new BerkeleyDb(mProxyConfig->getConfigData("DatabasePath", "./", true));
 
632
   }
 
633
   assert(mAbstractDb);
 
634
   if(!mAbstractDb->isSane())
 
635
   {
 
636
      CritLog(<<"Failed to open configuration database");
 
637
      cleanupObjects();
 
638
      return false;
 
639
   }
 
640
   if(mRuntimeAbstractDb && !mRuntimeAbstractDb->isSane())
 
641
   {
 
642
      CritLog(<<"Failed to open runtime configuration database");
 
643
      cleanupObjects();
 
644
      return false;
 
645
   }
 
646
   mProxyConfig->createDataStore(mAbstractDb, mRuntimeAbstractDb);
 
647
 
 
648
   // Create ImMemory Registration Database
 
649
   mRegSyncPort = mProxyConfig->getConfigInt("RegSyncPort", 0);
 
650
   // We only need removed records to linger if we have reg sync enabled
 
651
   if(!mRestarting)  // If we are restarting then we left the InMemoryRegistrationDb intact at shutdown - don't recreate
 
652
   {
 
653
      assert(!mRegistrationPersistenceManager);
 
654
      mRegistrationPersistenceManager = new InMemorySyncRegDb(mRegSyncPort ? 86400 /* 24 hours */ : 0 /* removeLingerSecs */);  // !slg! could make linger time a setting
 
655
   }
 
656
   assert(mRegistrationPersistenceManager);
 
657
 
 
658
   // Copy contacts from the StaticRegStore to the RegistrationPersistanceManager
 
659
   populateRegistrations();
 
660
 
 
661
   return true;
 
662
}
 
663
 
 
664
void
 
665
ReproRunner::createDialogUsageManager()
 
666
{
 
667
   // Create Profile settings for DUM Instance that handles ServerRegistration,
 
668
   // and potentially certificate subscription server
 
669
   SharedPtr<MasterProfile> profile(new MasterProfile);
 
670
   profile->clearSupportedMethods();
 
671
   profile->addSupportedMethod(resip::REGISTER);
 
672
#ifdef USE_SSL
 
673
   profile->addSupportedScheme(Symbols::Sips);
 
674
#endif
 
675
   if(InteropHelper::getOutboundSupported())
 
676
   {
 
677
      profile->addSupportedOptionTag(Token(Symbols::Outbound));
 
678
   }
 
679
   profile->addSupportedOptionTag(Token(Symbols::Path));
 
680
   if(mProxyConfig->getConfigBool("AllowBadReg", false))
 
681
   {
 
682
       profile->allowBadRegistrationEnabled() = true;
 
683
   }
 
684
   
 
685
   // Create DialogeUsageManager if Registrar or Certificate Server are enabled
 
686
   assert(!mRegistrar);
 
687
   assert(!mDum);
 
688
   assert(!mDumThread);
 
689
   mRegistrar = new Registrar;
 
690
   resip::MessageFilterRuleList ruleList;
 
691
   bool registrarEnabled = !mProxyConfig->getConfigBool("DisableRegistrar", false);
 
692
   bool certServerEnabled = mProxyConfig->getConfigBool("EnableCertServer", false);
 
693
   if (registrarEnabled || certServerEnabled)
 
694
   {
 
695
      mDum = new DialogUsageManager(*mSipStack);
 
696
      mDum->setMasterProfile(profile);
 
697
      addDomains(*mDum, false /* log? already logged when adding to Proxy - no need to log again*/);
 
698
   }
 
699
 
 
700
   // If registrar is enabled, configure DUM to handle REGISTER requests
 
701
   if (registrarEnabled)
 
702
   {   
 
703
      assert(mDum);
 
704
      assert(mRegistrationPersistenceManager);
 
705
      mDum->setServerRegistrationHandler(mRegistrar);
 
706
      mDum->setRegistrationPersistenceManager(mRegistrationPersistenceManager);
 
707
 
 
708
      // Install rules so that the registrar only gets REGISTERs
 
709
      resip::MessageFilterRule::MethodList methodList;
 
710
      methodList.push_back(resip::REGISTER);
 
711
      ruleList.push_back(MessageFilterRule(resip::MessageFilterRule::SchemeList(),
 
712
                                           resip::MessageFilterRule::DomainIsMe,
 
713
                                           methodList) );
 
714
   }
 
715
   
 
716
   // If Certificate Server is enabled, configure DUM to handle SUBSCRIBE and 
 
717
   // PUBLISH requests for events: credential and certificate
 
718
   assert(!mCertServer);
 
719
   if (certServerEnabled)
 
720
   {
 
721
#if defined(USE_SSL)
 
722
      mCertServer = new CertServer(*mDum);
 
723
 
 
724
      // Install rules so that the cert server receives SUBSCRIBEs and PUBLISHs
 
725
      resip::MessageFilterRule::MethodList methodList;
 
726
      resip::MessageFilterRule::EventList eventList;
 
727
      methodList.push_back(resip::SUBSCRIBE);
 
728
      methodList.push_back(resip::PUBLISH);
 
729
      eventList.push_back(resip::Symbols::Credential);
 
730
      eventList.push_back(resip::Symbols::Certificate);
 
731
      ruleList.push_back(MessageFilterRule(resip::MessageFilterRule::SchemeList(),
 
732
                                           resip::MessageFilterRule::DomainIsMe,
 
733
                                           methodList,
 
734
                                           eventList));
 
735
#endif
 
736
   }
 
737
 
 
738
   if (mDum)
 
739
   {
 
740
      bool enableCertAuth = mProxyConfig->getConfigBool("EnableCertificateAuthenticator", false);
 
741
      // Maintains existing behavior for non-TLS cert auth users
 
742
      bool digestChallengeThirdParties = !enableCertAuth;
 
743
 
 
744
      if(enableCertAuth)
 
745
      {
 
746
         // TODO: perhaps this should be initialised from the trusted node
 
747
         // monkey?  Or should the list of trusted TLS peers be independent
 
748
         // from the trusted node list?
 
749
         std::set<Data> trustedPeers;
 
750
         loadCommonNameMappings();
 
751
         SharedPtr<TlsPeerAuthManager> certAuth(new TlsPeerAuthManager(*mDum, mDum->dumIncomingTarget(), trustedPeers, true, mCommonNameMappings));
 
752
         mDum->addIncomingFeature(certAuth);
 
753
      }
 
754
 
 
755
      mSipAuthDisabled = mProxyConfig->getConfigBool("DisableAuth", false);
 
756
 
 
757
      // If Authentication is enabled, then configure DUM to authenticate requests
 
758
      if (!mSipAuthDisabled)
 
759
      {
 
760
         // Create UserAuthGrabber Worker Thread Pool if auth is enabled
 
761
         assert(!mAuthRequestDispatcher);
 
762
         int numAuthGrabberWorkerThreads = mProxyConfig->getConfigInt("NumAuthGrabberWorkerThreads", 2);
 
763
         if(numAuthGrabberWorkerThreads < 1) numAuthGrabberWorkerThreads = 1; // must have at least one thread
 
764
         std::auto_ptr<Worker> grabber(new UserAuthGrabber(mProxyConfig->getDataStore()->mUserStore));
 
765
         mAuthRequestDispatcher = new Dispatcher(grabber, mSipStack, numAuthGrabberWorkerThreads);
 
766
 
 
767
         SharedPtr<ServerAuthManager> 
 
768
            uasAuth( new ReproServerAuthManager(*mDum,
 
769
                                                mAuthRequestDispatcher,
 
770
                                                mProxyConfig->getDataStore()->mAclStore,
 
771
                                                !mProxyConfig->getConfigBool("DisableAuthInt", false) /*useAuthInt*/,
 
772
                                                mProxyConfig->getConfigBool("RejectBadNonces", false),
 
773
                                                digestChallengeThirdParties));
 
774
         mDum->setServerAuthManager(uasAuth);
 
775
      }
 
776
 
 
777
      // Set the MessageFilterRuleList on DUM and create a thread to run DUM in
 
778
      mDum->setMessageFilterRuleList(ruleList);
 
779
      mDumThread = new DumThread(*mDum);
 
780
   }   
 
781
}
 
782
 
 
783
bool
 
784
ReproRunner::createProxy()
 
785
{
 
786
   // Create AsyncProcessorDispatcher thread pool that is shared by the processsors for
 
787
   // any asyncronous tasks (ie: RequestFilter and MessageSilo processors)
 
788
   int numAsyncProcessorWorkerThreads = mProxyConfig->getConfigInt("NumAsyncProcessorWorkerThreads", 2);
 
789
   if(numAsyncProcessorWorkerThreads > 0)
 
790
   {
 
791
      assert(!mAsyncProcessorDispatcher);
 
792
      mAsyncProcessorDispatcher = new Dispatcher(std::auto_ptr<Worker>(new AsyncProcessorWorker), 
 
793
                                                 mSipStack, 
 
794
                                                 numAsyncProcessorWorkerThreads);
 
795
   }
 
796
 
 
797
   // Create proxy processor chains
 
798
   /* Explanation:  "Monkeys" are processors which operate on incoming requests
 
799
                    "Lemurs"  are processors which operate on incoming responses
 
800
                    "Baboons" are processors which operate on a request for each target  
 
801
                              as the request is about to be forwarded to that target */
 
802
   // Make Monkeys
 
803
   assert(!mMonkeys);
 
804
   mMonkeys = new ProcessorChain(Processor::REQUEST_CHAIN);
 
805
   makeRequestProcessorChain(*mMonkeys);
 
806
   InfoLog(<< *mMonkeys);
 
807
 
 
808
   // Make Lemurs
 
809
   assert(!mLemurs);
 
810
   mLemurs = new ProcessorChain(Processor::RESPONSE_CHAIN);
 
811
   makeResponseProcessorChain(*mLemurs);
 
812
   InfoLog(<< *mLemurs);
 
813
 
 
814
   // Make Baboons
 
815
   assert(!mBaboons);
 
816
   mBaboons = new ProcessorChain(Processor::TARGET_CHAIN);
 
817
   makeTargetProcessorChain(*mBaboons);
 
818
   InfoLog(<< *mBaboons);
 
819
 
 
820
   // Create main Proxy class
 
821
   assert(!mProxy);
 
822
   mProxy = new Proxy(*mSipStack, 
 
823
                      *mProxyConfig, 
 
824
                      *mMonkeys, 
 
825
                      *mLemurs, 
 
826
                      *mBaboons);
 
827
   mHttpRealm = addDomains(*mProxy, true);
 
828
 
 
829
   // Register the Proxy class a stack transaction user
 
830
   // Note:  This is done after creating the DialogUsageManager so that it acts 
 
831
   // like a catchall and will handle all requests the DUM does not
 
832
   mSipStack->registerTransactionUser(*mProxy);
 
833
 
 
834
   return true;
 
835
}
 
836
 
 
837
void 
 
838
ReproRunner::populateRegistrations()
 
839
{
 
840
   assert(mRegistrationPersistenceManager);
 
841
   assert(mProxyConfig);
 
842
   assert(mProxyConfig->getDataStore());
 
843
 
 
844
   // Copy contacts from the StaticRegStore to the RegistrationPersistanceManager
 
845
   StaticRegStore::StaticRegRecordMap& staticRegList = mProxyConfig->getDataStore()->mStaticRegStore.getStaticRegList();
 
846
   StaticRegStore::StaticRegRecordMap::iterator it = staticRegList.begin();
 
847
   for(; it != staticRegList.end(); it++)
 
848
   {
 
849
      try
 
850
      {
 
851
         Uri aor(it->second.mAor);
 
852
 
 
853
         ContactInstanceRecord rec;
 
854
         rec.mContact = NameAddr(it->second.mContact);
 
855
         rec.mSipPath = NameAddrs(it->second.mPath);
 
856
         rec.mRegExpires = NeverExpire;
 
857
         rec.mSyncContact = true;  // Tag this permanent contact as being a syncronized contact so that it will
 
858
                                    // be syncronized to a paired server (this is actually configuration information)
 
859
         mRegistrationPersistenceManager->updateContact(aor, rec);
 
860
      }
 
861
      catch(resip::ParseBuffer::Exception& e)  
 
862
      {
 
863
         // This should never happen, since the format should be verified before writing to DB
 
864
         ErrLog(<<"Failed to apply a static registration due to parse error: " << e);
 
865
      }
 
866
   }
 
867
}
 
868
 
 
869
bool
 
870
ReproRunner::createWebAdmin()
 
871
{
 
872
   assert(!mWebAdmin);
 
873
   assert(!mWebAdminThread);
 
874
   int httpPort = mProxyConfig->getConfigInt("HttpPort", 5080);
 
875
   if (httpPort) 
 
876
   {
 
877
      mWebAdmin = new WebAdmin(*mProxy,
 
878
                               *mRegistrationPersistenceManager, 
 
879
                               mHttpRealm, 
 
880
                               httpPort);
 
881
      if (!mWebAdmin->isSane())
 
882
      {
 
883
         CritLog(<<"Failed to start the WebAdmin");
 
884
         cleanupObjects();
 
885
         return false;
 
886
      }
 
887
      mWebAdminThread = new WebAdminThread(*mWebAdmin);
 
888
   }
 
889
   return true;
 
890
}
 
891
 
 
892
void
 
893
ReproRunner::createRegSync()
 
894
{
 
895
   assert(!mRegSyncClient);
 
896
   assert(!mRegSyncServerV4);
 
897
   assert(!mRegSyncServerV6);
 
898
   assert(!mRegSyncServerThread);
 
899
   if(mRegSyncPort != 0)
 
900
   {
 
901
      std::list<RegSyncServer*> regSyncServerList;
 
902
      if(mUseV4) 
 
903
      {
 
904
         mRegSyncServerV4 = new RegSyncServer(dynamic_cast<InMemorySyncRegDb*>(mRegistrationPersistenceManager), mRegSyncPort, V4);
 
905
         regSyncServerList.push_back(mRegSyncServerV4);
 
906
      }
 
907
      if(mUseV6) 
 
908
      {
 
909
         mRegSyncServerV6 = new RegSyncServer(dynamic_cast<InMemorySyncRegDb*>(mRegistrationPersistenceManager), mRegSyncPort, V6);
 
910
         regSyncServerList.push_back(mRegSyncServerV6);
 
911
      }
 
912
      if(!regSyncServerList.empty())
 
913
      {
 
914
         mRegSyncServerThread = new RegSyncServerThread(regSyncServerList);
 
915
      }
 
916
      Data regSyncPeerAddress(mProxyConfig->getConfigData("RegSyncPeer", ""));
 
917
      if(!regSyncPeerAddress.empty())
 
918
      {
 
919
         mRegSyncClient = new RegSyncClient(dynamic_cast<InMemorySyncRegDb*>(mRegistrationPersistenceManager), regSyncPeerAddress, mRegSyncPort);
 
920
      }
 
921
   }
 
922
}
 
923
 
 
924
void
 
925
ReproRunner::createCommandServer()
 
926
{
 
927
   assert(!mCommandServerV4);
 
928
   assert(!mCommandServerV6);
 
929
   assert(!mCommandServerThread);
 
930
   int commandPort = mProxyConfig->getConfigInt("CommandPort", 5081);
 
931
   if(commandPort != 0)
 
932
   {
 
933
      std::list<CommandServer*> commandServerList;
 
934
      if(mUseV4) 
 
935
      {
 
936
         mCommandServerV4 = new CommandServer(*this, commandPort, V4);
 
937
         commandServerList.push_back(mCommandServerV4);
 
938
      }
 
939
      if(mUseV6) 
 
940
      {
 
941
         mCommandServerV6 = new CommandServer(*this, commandPort, V6);
 
942
         commandServerList.push_back(mCommandServerV6);
 
943
      }
 
944
      if(!commandServerList.empty())
 
945
      {
 
946
         mCommandServerThread = new CommandServerThread(commandServerList);
 
947
      }
 
948
   }
 
949
}
 
950
 
 
951
Data
 
952
ReproRunner::addDomains(TransactionUser& tu, bool log)
 
953
{
 
954
   assert(mProxyConfig);
 
955
   Data realm;
 
956
   
 
957
   std::vector<Data> configDomains;
 
958
   if(mProxyConfig->getConfigValue("Domains", configDomains))
 
959
   {
 
960
      for (std::vector<Data>::const_iterator i=configDomains.begin(); 
 
961
         i != configDomains.end(); ++i)
 
962
      {
 
963
         if(log) InfoLog (<< "Adding domain " << *i << " from command line");
 
964
         tu.addDomain(*i);
 
965
         if ( realm.empty() )
 
966
         {
 
967
            realm = *i;
 
968
         }
 
969
      }
 
970
   }
 
971
 
 
972
   const ConfigStore::ConfigData& dList = mProxyConfig->getDataStore()->mConfigStore.getConfigs();
 
973
   for (ConfigStore::ConfigData::const_iterator i=dList.begin(); 
 
974
           i != dList.end(); ++i)
 
975
   {
 
976
      if(log) InfoLog (<< "Adding domain " << i->second.mDomain << " from config");
 
977
      tu.addDomain( i->second.mDomain );
 
978
      if ( realm.empty() )
 
979
      {
 
980
         realm = i->second.mDomain;
 
981
      }
 
982
   }
 
983
 
 
984
   /* All of this logic has been commented out - the sysadmin must explicitly
 
985
      add any of the items below to the Domains config option in repro.config
 
986
 
 
987
   Data localhostname(DnsUtil::getLocalHostName());
 
988
   if(log) InfoLog (<< "Adding local hostname domain " << localhostname );
 
989
   tu.addDomain(localhostname);
 
990
   if ( realm.empty() )
 
991
   {
 
992
      realm = localhostname;
 
993
   }
 
994
 
 
995
   if(log) InfoLog (<< "Adding localhost domain.");
 
996
   tu.addDomain("localhost");
 
997
   if ( realm.empty() )
 
998
   {
 
999
      realm = "localhost";
 
1000
   }
 
1001
   
 
1002
   list<pair<Data,Data> > ips = DnsUtil::getInterfaces();
 
1003
   for ( list<pair<Data,Data> >::const_iterator i=ips.begin(); i!=ips.end(); i++)
 
1004
   {
 
1005
      if(log) InfoLog( << "Adding domain for IP " << i->second << " from interface " << i->first  );
 
1006
      tu.addDomain(i->second);
 
1007
   }
 
1008
 
 
1009
   if(log) InfoLog (<< "Adding 127.0.0.1 domain.");
 
1010
   tu.addDomain("127.0.0.1"); */
 
1011
 
 
1012
   if( realm.empty() )
 
1013
      realm = "Unconfigured";
 
1014
 
 
1015
   return realm;
 
1016
}
 
1017
 
 
1018
bool
 
1019
ReproRunner::addTransports(bool& allTransportsSpecifyRecordRoute)
 
1020
{
 
1021
   assert(mProxyConfig);
 
1022
   assert(mSipStack);
 
1023
   allTransportsSpecifyRecordRoute=false;
 
1024
   bool useEmailAsSIP = mProxyConfig->getConfigBool("TLSUseEmailAsSIP", false);
 
1025
   try
 
1026
   {
 
1027
      // Check if advanced transport settings are provided
 
1028
      unsigned int transportNum = 1;
 
1029
      Data settingKeyBase("Transport" + Data(transportNum));
 
1030
      Data interfaceSettingKey(settingKeyBase + "Interface");
 
1031
      Data interfaceSettings = mProxyConfig->getConfigData(interfaceSettingKey, "", true);
 
1032
      if(!interfaceSettings.empty())
 
1033
      {
 
1034
         // Sample config file format for advanced transport settings
 
1035
         // Transport1Interface = 192.168.1.106:5061
 
1036
         // Transport1Type = TLS
 
1037
         // Transport1TlsDomain = sipdomain.com
 
1038
         // Transport1TlsClientVerification = None
 
1039
         // Transport1RecordRouteUri = sip:sipdomain.com;transport=TLS
 
1040
         // Transport1RcvBufLen = 2000
 
1041
 
 
1042
         allTransportsSpecifyRecordRoute = true;
 
1043
 
 
1044
         const char *anchor;
 
1045
         while(!interfaceSettings.empty())
 
1046
         {
 
1047
            Data typeSettingKey(settingKeyBase + "Type");
 
1048
            Data tlsDomainSettingKey(settingKeyBase + "TlsDomain");
 
1049
            Data tlsCVMSettingKey(settingKeyBase + "TlsClientVerification");
 
1050
            Data recordRouteUriSettingKey(settingKeyBase + "RecordRouteUri");
 
1051
            Data rcvBufSettingKey(settingKeyBase + "RcvBufLen");
 
1052
 
 
1053
            // Parse out interface settings
 
1054
            ParseBuffer pb(interfaceSettings);
 
1055
            anchor = pb.position();
 
1056
            pb.skipToChar(':');
 
1057
            if(!pb.eof())
 
1058
            {
 
1059
               Data ipAddr;
 
1060
               Data portData;
 
1061
               pb.data(ipAddr, anchor);
 
1062
               pb.skipChar();
 
1063
               anchor = pb.position();
 
1064
               pb.skipToEnd();
 
1065
               pb.data(portData, anchor);
 
1066
               if(!DnsUtil::isIpAddress(ipAddr))
 
1067
               {
 
1068
                  CritLog(<< "Malformed IP-address found in " << interfaceSettingKey << " setting: " << ipAddr);
 
1069
               }
 
1070
               int port = portData.convertInt();
 
1071
               if(port == 0)
 
1072
               {
 
1073
                  CritLog(<< "Invalid port found in " << interfaceSettingKey << " setting: " << port);
 
1074
               }
 
1075
               TransportType tt = Tuple::toTransport(mProxyConfig->getConfigData(typeSettingKey, "UDP"));
 
1076
               if(tt == UNKNOWN_TRANSPORT)
 
1077
               {
 
1078
                  CritLog(<< "Unknown transport type found in " << typeSettingKey << " setting: " << mProxyConfig->getConfigData(typeSettingKey, "UDP"));
 
1079
               }
 
1080
               Data tlsDomain = mProxyConfig->getConfigData(tlsDomainSettingKey, "");
 
1081
               Data tlsCVMValue = mProxyConfig->getConfigData(tlsCVMSettingKey, "NONE");
 
1082
               SecurityTypes::TlsClientVerificationMode cvm = SecurityTypes::None;
 
1083
               if(isEqualNoCase(tlsCVMValue, "Optional"))
 
1084
               {
 
1085
                  cvm = SecurityTypes::Optional;
 
1086
               }
 
1087
               else if(isEqualNoCase(tlsCVMValue, "Mandatory"))
 
1088
               {
 
1089
                  cvm = SecurityTypes::Mandatory;
 
1090
               }
 
1091
               else if(!isEqualNoCase(tlsCVMValue, "None"))
 
1092
               {
 
1093
                  CritLog(<< "Unknown TLS client verification mode found in " << tlsCVMSettingKey << " setting: " << tlsCVMValue);
 
1094
               }
 
1095
               int rcvBufLen = mProxyConfig->getConfigInt(rcvBufSettingKey, 0);
 
1096
               Transport *t = mSipStack->addTransport(tt,
 
1097
                                 port,
 
1098
                                 DnsUtil::isIpV6Address(ipAddr) ? V6 : V4,
 
1099
                                 StunEnabled, 
 
1100
                                 ipAddr,       // interface to bind to
 
1101
                                 tlsDomain,
 
1102
                                 Data::Empty,  // private key passphrase - not currently used
 
1103
                                 SecurityTypes::TLSv1, // sslType
 
1104
                                 0,            // transport flags
 
1105
                                 cvm,          // tls client verification mode
 
1106
                                 useEmailAsSIP);
 
1107
 
 
1108
               if (t && rcvBufLen>0 )
 
1109
               {
 
1110
#if defined(RESIP_SIPSTACK_HAVE_FDPOLL)
 
1111
                  // this new method is part of the epoll changeset,
 
1112
                  // which isn't commited yet.
 
1113
                  t->setRcvBufLen(rcvBufLen);
 
1114
#else
 
1115
                   assert(0);
 
1116
#endif
 
1117
               }
 
1118
 
 
1119
               Data recordRouteUri = mProxyConfig->getConfigData(recordRouteUriSettingKey, "");
 
1120
               if(!recordRouteUri.empty())
 
1121
               {
 
1122
                  try
 
1123
                  {
 
1124
                     if(isEqualNoCase(recordRouteUri, "auto")) // auto generated record route uri
 
1125
                     {
 
1126
                        if(tt == TLS || tt == DTLS)
 
1127
                        {
 
1128
                           NameAddr rr;
 
1129
                           rr.uri().host()=tlsDomain;
 
1130
                           rr.uri().port()=port;
 
1131
                           rr.uri().param(resip::p_transport)=resip::Tuple::toDataLower(tt);
 
1132
                           t->setRecordRoute(rr);
 
1133
                           InfoLog (<< "Transport specific record-route enabled (generated): " << rr);
 
1134
                        }
 
1135
                        else
 
1136
                        {
 
1137
                           NameAddr rr;
 
1138
                           rr.uri().host()=ipAddr;
 
1139
                           rr.uri().port()=port;
 
1140
                           rr.uri().param(resip::p_transport)=resip::Tuple::toDataLower(tt);
 
1141
                           t->setRecordRoute(rr);
 
1142
                           InfoLog (<< "Transport specific record-route enabled (generated): " << rr);
 
1143
                        }
 
1144
                     }
 
1145
                     else
 
1146
                     {
 
1147
                        NameAddr rr(recordRouteUri);
 
1148
                        t->setRecordRoute(rr);
 
1149
                        InfoLog (<< "Transport specific record-route enabled: " << rr);
 
1150
                     }
 
1151
                  }
 
1152
                  catch(BaseException& e)
 
1153
                  {
 
1154
                     ErrLog (<< "Invalid uri provided in " << recordRouteUriSettingKey << " setting (ignoring): " << e);
 
1155
                     allTransportsSpecifyRecordRoute = false;
 
1156
                  }
 
1157
               }
 
1158
               else 
 
1159
               {
 
1160
                  allTransportsSpecifyRecordRoute = false;
 
1161
               }
 
1162
            }
 
1163
            else
 
1164
            {
 
1165
               CritLog(<< "Port not specified in " << interfaceSettingKey << " setting: expected format is <IPAddress>:<Port>");
 
1166
               return false;
 
1167
            }
 
1168
 
 
1169
            // Check if there is another transport
 
1170
            transportNum++;
 
1171
            settingKeyBase = Data("Transport" + Data(transportNum));
 
1172
            interfaceSettingKey = Data(settingKeyBase + "Interface");
 
1173
            interfaceSettings = mProxyConfig->getConfigData(interfaceSettingKey, "", true);
 
1174
         }
 
1175
      }
 
1176
      else
 
1177
      {
 
1178
         int udpPort = mProxyConfig->getConfigInt("UDPPort", 5060);
 
1179
         int tcpPort = mProxyConfig->getConfigInt("TCPPort", 5060);
 
1180
         int tlsPort = mProxyConfig->getConfigInt("TLSPort", 5061);
 
1181
         int dtlsPort = mProxyConfig->getConfigInt("DTLSPort", 0);
 
1182
         Data tlsDomain = mProxyConfig->getConfigData("TLSDomainName", "");
 
1183
         Data tlsCVMValue = mProxyConfig->getConfigData("TLSClientVerification", "NONE");
 
1184
         SecurityTypes::TlsClientVerificationMode cvm = SecurityTypes::None;
 
1185
         if(isEqualNoCase(tlsCVMValue, "Optional"))
 
1186
         {
 
1187
            cvm = SecurityTypes::Optional;
 
1188
         }
 
1189
         else if(isEqualNoCase(tlsCVMValue, "Mandatory"))
 
1190
         {
 
1191
            cvm = SecurityTypes::Mandatory;
 
1192
         }
 
1193
         else if(!isEqualNoCase(tlsCVMValue, "None"))
 
1194
         {
 
1195
            CritLog(<< "Unknown TLS client verification mode found in TLSClientVerification setting: " << tlsCVMValue);
 
1196
         }
 
1197
 
 
1198
         if (udpPort)
 
1199
         {
 
1200
            if (mUseV4) mSipStack->addTransport(UDP, udpPort, V4, StunEnabled);
 
1201
            if (mUseV6) mSipStack->addTransport(UDP, udpPort, V6, StunEnabled);
 
1202
         }
 
1203
         if (tcpPort)
 
1204
         {
 
1205
            if (mUseV4) mSipStack->addTransport(TCP, tcpPort, V4, StunEnabled);
 
1206
            if (mUseV6) mSipStack->addTransport(TCP, tcpPort, V6, StunEnabled);
 
1207
         }
 
1208
         if (tlsPort)
 
1209
         {
 
1210
            if (mUseV4) mSipStack->addTransport(TLS, tlsPort, V4, StunEnabled, Data::Empty, tlsDomain, Data::Empty, SecurityTypes::TLSv1, 0, cvm, useEmailAsSIP);
 
1211
            if (mUseV6) mSipStack->addTransport(TLS, tlsPort, V6, StunEnabled, Data::Empty, tlsDomain, Data::Empty, SecurityTypes::TLSv1, 0, cvm, useEmailAsSIP);
 
1212
         }
 
1213
         if (dtlsPort)
 
1214
         {
 
1215
            if (mUseV4) mSipStack->addTransport(DTLS, dtlsPort, V4, StunEnabled, Data::Empty, tlsDomain);
 
1216
            if (mUseV6) mSipStack->addTransport(DTLS, dtlsPort, V6, StunEnabled, Data::Empty, tlsDomain);
 
1217
         }
 
1218
      }
 
1219
   }
 
1220
   catch (BaseException& e)
 
1221
   {
 
1222
      std::cerr << "Likely a port is already in use" << endl;
 
1223
      InfoLog (<< "Caught: " << e);
 
1224
      return false;
 
1225
   }
 
1226
   return true;
 
1227
}
 
1228
 
 
1229
void 
 
1230
ReproRunner::addProcessor(repro::ProcessorChain& chain, std::auto_ptr<Processor> processor)
 
1231
{
 
1232
   chain.addProcessor(processor);
 
1233
}
 
1234
 
 
1235
void
 
1236
ReproRunner::loadCommonNameMappings()
 
1237
{
 
1238
   // Already loaded?
 
1239
   if(!mCommonNameMappings.empty())
 
1240
      return;
 
1241
 
 
1242
   Data mappingsFileName = mProxyConfig->getConfigData("CommonNameMappings", "");
 
1243
   if(mappingsFileName.empty())
 
1244
      return;
 
1245
 
 
1246
   InfoLog(<< "trying to load common name mappings from file: " << mappingsFileName);
 
1247
 
 
1248
   ifstream mappingsFile(mappingsFileName.c_str());
 
1249
   if(!mappingsFile)
 
1250
   {
 
1251
      throw std::runtime_error("Error opening/reading mappings file");
 
1252
   }
 
1253
 
 
1254
   string sline;
 
1255
   while(getline(mappingsFile, sline))
 
1256
   {
 
1257
      Data line(sline);
 
1258
      Data cn;
 
1259
      PermittedFromAddresses permitted;
 
1260
      ParseBuffer pb(line);
 
1261
 
 
1262
      pb.skipWhitespace();
 
1263
      const char * anchor = pb.position();
 
1264
      if(pb.eof() || *anchor == '#') continue;  // if line is a comment or blank then skip it
 
1265
 
 
1266
      // Look for end of name
 
1267
      pb.skipToOneOf("\t");
 
1268
      pb.data(cn, anchor);
 
1269
      pb.skipChar('\t');
 
1270
 
 
1271
      while(!pb.eof())
 
1272
      {
 
1273
         pb.skipWhitespace();
 
1274
         if(pb.eof())
 
1275
            continue;
 
1276
 
 
1277
         Data value;
 
1278
         anchor = pb.position();
 
1279
         pb.skipToOneOf(",\r\n ");
 
1280
         pb.data(value, anchor);
 
1281
         if(!value.empty())
 
1282
         {
 
1283
            StackLog(<< "Loading CN '" << cn << "', found mapping '" << value << "'");
 
1284
            permitted.insert(value);
 
1285
         }
 
1286
         if(!pb.eof())
 
1287
            pb.skipChar();
 
1288
      }
 
1289
 
 
1290
      DebugLog(<< "Loaded mapping for CN '" << cn << "', " << permitted.size() << " mapping(s)");
 
1291
      mCommonNameMappings[cn] = permitted;
 
1292
   }
 
1293
}
 
1294
 
 
1295
void  // Monkeys
 
1296
ReproRunner::makeRequestProcessorChain(ProcessorChain& chain)
 
1297
{
 
1298
   assert(mProxyConfig);
 
1299
   assert(mRegistrationPersistenceManager);
 
1300
 
 
1301
   // Add strict route fixup monkey
 
1302
   addProcessor(chain, std::auto_ptr<Processor>(new StrictRouteFixup));
 
1303
 
 
1304
   // Add is trusted node monkey
 
1305
   addProcessor(chain, std::auto_ptr<Processor>(new IsTrustedNode(*mProxyConfig)));
 
1306
 
 
1307
   // Add Certificate Authenticator - if required
 
1308
   if(mProxyConfig->getConfigBool("EnableCertificateAuthenticator", false))
 
1309
   {
 
1310
      // TODO: perhaps this should be initialised from the trusted node
 
1311
      // monkey?  Or should the list of trusted TLS peers be independent
 
1312
      // from the trusted node list?
 
1313
      // Should we used the same trustedPeers object that was
 
1314
      // passed to TlsPeerAuthManager perhaps?
 
1315
      std::set<Data> trustedPeers;
 
1316
      loadCommonNameMappings();
 
1317
      addProcessor(chain, std::auto_ptr<Processor>(new CertificateAuthenticator(*mProxyConfig, mSipStack, trustedPeers, true, mCommonNameMappings)));
 
1318
   }
 
1319
 
 
1320
   // Add digest authenticator monkey - if required
 
1321
   if (!mSipAuthDisabled)
 
1322
   {
 
1323
      assert(mAuthRequestDispatcher);
 
1324
      DigestAuthenticator* da = new DigestAuthenticator(*mProxyConfig, mAuthRequestDispatcher);
 
1325
 
 
1326
      addProcessor(chain, std::auto_ptr<Processor>(da)); 
 
1327
   }
 
1328
 
 
1329
   // Add am I responsible monkey
 
1330
   addProcessor(chain, std::auto_ptr<Processor>(new AmIResponsible)); 
 
1331
 
 
1332
   // Add RequestFilter monkey
 
1333
   if(!mProxyConfig->getConfigBool("DisableRequestFilterProcessor", false))
 
1334
   {
 
1335
      if(mAsyncProcessorDispatcher)
 
1336
      {
 
1337
         addProcessor(chain, std::auto_ptr<Processor>(new RequestFilter(*mProxyConfig, mAsyncProcessorDispatcher)));
 
1338
      }
 
1339
      else
 
1340
      {
 
1341
         WarningLog(<< "Could not start RequestFilter Processor due to no worker thread pool (NumAsyncProcessorWorkerThreads=0)");
 
1342
      }
 
1343
   }
 
1344
 
 
1345
   // [TODO] support for GRUU is on roadmap.  When it is added the GruuMonkey will go here
 
1346
      
 
1347
   // [TODO] support for Manipulating Tel URIs is on the roadmap.
 
1348
   //        When added, the telUriMonkey will go here 
 
1349
 
 
1350
   std::vector<Data> routeSet;
 
1351
   mProxyConfig->getConfigValue("Routes", routeSet);
 
1352
   if (routeSet.empty())
 
1353
   {
 
1354
      // add static route monkey
 
1355
      addProcessor(chain, std::auto_ptr<Processor>(new StaticRoute(*mProxyConfig))); 
 
1356
   }
 
1357
   else
 
1358
   {
 
1359
      // add simple static route monkey
 
1360
      addProcessor(chain, std::auto_ptr<Processor>(new SimpleStaticRoute(*mProxyConfig))); 
 
1361
   }
 
1362
 
 
1363
   // Add location server monkey
 
1364
   addProcessor(chain, std::auto_ptr<Processor>(new LocationServer(*mProxyConfig, *mRegistrationPersistenceManager, mAuthRequestDispatcher)));
 
1365
 
 
1366
   // Add message silo monkey
 
1367
   if(mProxyConfig->getConfigBool("MessageSiloEnabled", false))
 
1368
   {
 
1369
      if(mAsyncProcessorDispatcher && mRegistrar)
 
1370
      {
 
1371
         MessageSilo* silo = new MessageSilo(*mProxyConfig, mAsyncProcessorDispatcher);
 
1372
         mRegistrar->addRegistrarHandler(silo);
 
1373
         addProcessor(chain, std::auto_ptr<Processor>(silo));
 
1374
      }
 
1375
      else
 
1376
      {
 
1377
         WarningLog(<< "Could not start MessageSilo Processor due to no worker thread pool (NumAsyncProcessorWorkerThreads=0) or Registrar");
 
1378
      }
 
1379
   }
 
1380
}
 
1381
 
 
1382
void  // Lemurs
 
1383
ReproRunner::makeResponseProcessorChain(ProcessorChain& chain)
 
1384
{
 
1385
   assert(mProxyConfig);
 
1386
   assert(mRegistrationPersistenceManager);
 
1387
 
 
1388
   // Add outbound target handler lemur
 
1389
   addProcessor(chain, std::auto_ptr<Processor>(new OutboundTargetHandler(*mRegistrationPersistenceManager))); 
 
1390
 
 
1391
   if (mProxyConfig->getConfigBool("RecursiveRedirect", false))
 
1392
   {
 
1393
      // Add recursive redirect lemur
 
1394
      addProcessor(chain, std::auto_ptr<Processor>(new RecursiveRedirect)); 
 
1395
   }
 
1396
}
 
1397
 
 
1398
void  // Baboons
 
1399
ReproRunner::makeTargetProcessorChain(ProcessorChain& chain)
 
1400
{
 
1401
   assert(mProxyConfig);
 
1402
 
 
1403
#ifndef RESIP_FIXED_POINT
 
1404
   if(mProxyConfig->getConfigBool("GeoProximityTargetSorting", false))
 
1405
   {
 
1406
      addProcessor(chain, std::auto_ptr<Processor>(new GeoProximityTargetSorter(*mProxyConfig)));
 
1407
   }
 
1408
#endif
 
1409
 
 
1410
   if(mProxyConfig->getConfigBool("QValue", true))
 
1411
   {
 
1412
      // Add q value target handler baboon
 
1413
      addProcessor(chain, std::auto_ptr<Processor>(new QValueTargetHandler(*mProxyConfig))); 
 
1414
   }
 
1415
   
 
1416
   // Add simple target handler baboon
 
1417
   addProcessor(chain, std::auto_ptr<Processor>(new SimpleTargetHandler)); 
 
1418
}
 
1419
 
 
1420
 
 
1421
/* ====================================================================
 
1422
 * The Vovida Software License, Version 1.0 
 
1423
 * 
 
1424
 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
 
1425
 * 
 
1426
 * Redistribution and use in source and binary forms, with or without
 
1427
 * modification, are permitted provided that the following conditions
 
1428
 * are met:
 
1429
 * 
 
1430
 * 1. Redistributions of source code must retain the above copyright
 
1431
 *    notice, this list of conditions and the following disclaimer.
 
1432
 * 
 
1433
 * 2. Redistributions in binary form must reproduce the above copyright
 
1434
 *    notice, this list of conditions and the following disclaimer in
 
1435
 *    the documentation and/or other materials provided with the
 
1436
 *    distribution.
 
1437
 * 
 
1438
 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
 
1439
 *    and "Vovida Open Communication Application Library (VOCAL)" must
 
1440
 *    not be used to endorse or promote products derived from this
 
1441
 *    software without prior written permission. For written
 
1442
 *    permission, please contact vocal@vovida.org.
 
1443
 *
 
1444
 * 4. Products derived from this software may not be called "VOCAL", nor
 
1445
 *    may "VOCAL" appear in their name, without prior written
 
1446
 *    permission of Vovida Networks, Inc.
 
1447
 * 
 
1448
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
 
1449
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
1450
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
 
1451
 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
 
1452
 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
 
1453
 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
 
1454
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
1455
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 
1456
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 
1457
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
1458
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 
1459
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 
1460
 * DAMAGE.
 
1461
 * 
 
1462
 * ====================================================================
 
1463
 */