/[resiprocate]/branches/b-directory-reorg/sip/resiprocate/SipStack.cxx
ViewVC logotype

Contents of /branches/b-directory-reorg/sip/resiprocate/SipStack.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5271 - (show annotations) (download)
Thu Aug 18 23:43:07 2005 UTC (14 years, 3 months ago) by jason
File size: 16112 byte(s)
new directory reorg proposal
1 #if defined(HAVE_CONFIG_H)
2 #include "resiprocate/config.hxx"
3 #endif
4
5 #ifndef WIN32
6 #include <unistd.h>
7 #include <netdb.h>
8 #include <netinet/in.h>
9 #include <arpa/inet.h>
10 #endif
11
12 #include "resiprocate/os/compat.hxx"
13 #include "resiprocate/os/Data.hxx"
14 #include "resiprocate/os/Fifo.hxx"
15 #include "resiprocate/os/Logger.hxx"
16 #include "resiprocate/os/Random.hxx"
17 #include "resiprocate/os/Socket.hxx"
18 #include "resiprocate/os/Timer.hxx"
19
20 #include "resiprocate/Message.hxx"
21 #include "resiprocate/Security.hxx"
22 #include "resiprocate/ShutdownMessage.hxx"
23 #include "resiprocate/SipMessage.hxx"
24 #include "resiprocate/ApplicationMessage.hxx"
25 #include "resiprocate/SipStack.hxx"
26 #include "resiprocate/os/Inserter.hxx"
27 #include "resiprocate/StatisticsManager.hxx"
28 #include "resiprocate/os/AsyncProcessHandler.hxx"
29 #include "resiprocate/TcpTransport.hxx"
30 #include "resiprocate/TlsTransport.hxx"
31 #include "resiprocate/UdpTransport.hxx"
32 #include "resiprocate/DtlsTransport.hxx"
33 #include "resiprocate/TransactionUser.hxx"
34 #include "resiprocate/TransactionUserMessage.hxx"
35 #include "resiprocate/os/WinLeakCheck.hxx"
36
37 #ifdef WIN32
38 #pragma warning( disable : 4355 )
39 #endif
40
41 using namespace resip;
42
43 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP
44
45 SipStack::SipStack(Security* pSecurity,
46 const DnsStub::NameserverList& additional,
47 AsyncProcessHandler* handler, bool stateless) :
48 #ifdef USE_SSL
49 mSecurity( pSecurity ? pSecurity : new Security("~/")),
50 #else
51 mSecurity(0),
52 #endif
53 mDnsStub(new DnsStub(additional)),
54 mAsyncProcessHandler(handler),
55 mTUFifo(TransactionController::MaxTUFifoTimeDepthSecs,
56 TransactionController::MaxTUFifoSize),
57 mAppTimers(mTuSelector),
58 mStatsManager(*this),
59 mTransactionController(*this),
60 mShuttingDown(false),
61 mTuSelector(mTUFifo)
62 {
63 Timer::getTimeMs(); // initalize time offsets
64 Random::initialize();
65 initNetwork();
66 if (pSecurity)
67 {
68 pSecurity->preload();
69 }
70
71 assert(!mShuttingDown);
72 }
73
74 SipStack::~SipStack()
75 {
76 DebugLog (<< "SipStack::~SipStack()");
77 #ifdef USE_SSL
78 delete mSecurity;
79 #endif
80 delete mDnsStub;
81 }
82
83 void
84 SipStack::shutdown()
85 {
86 InfoLog (<< "Shutting down sip stack " << this);
87
88 static Mutex shutDownMutex;
89 {
90 Lock lock(shutDownMutex);
91 assert(!mShuttingDown);
92 mShuttingDown = true;
93 }
94
95 mTransactionController.shutdown();
96 }
97
98 void
99 SipStack::addTransport( TransportType protocol,
100 int port,
101 IpVersion version,
102 StunSetting stun,
103 const Data& ipInterface,
104 const Data& sipDomainname,
105 const Data& privateKeyPassPhrase,
106 SecurityTypes::SSLType sslType)
107 {
108 assert(!mShuttingDown);
109 assert( port > 0 );
110 InternalTransport* transport=0;
111 Fifo<TransactionMessage>& stateMacFifo = mTransactionController.transportSelector().stateMacFifo();
112 try
113 {
114 switch (protocol)
115 {
116 case UDP:
117 transport = new UdpTransport(stateMacFifo, port, version, stun, ipInterface);
118 break;
119 case TCP:
120 transport = new TcpTransport(stateMacFifo, port, version, ipInterface);
121 break;
122 case TLS:
123 #if defined( USE_SSL )
124 transport = new TlsTransport(stateMacFifo,
125 port,
126 version,
127 ipInterface,
128 *mSecurity,
129 sipDomainname,
130 sslType);
131 #else
132 CritLog (<< "TLS not supported in this stack. You don't have openssl");
133 assert(0);
134 #endif
135 break;
136 case DTLS:
137 #if defined( USE_DTLS )
138 transport = new DtlsTransport(stateMacFifo,
139 port,
140 version, // !jf! stun
141 ipInterface,
142 *mSecurity,
143 sipDomainname);
144 #else
145 CritLog (<< "TLS not supported in this stack. You don't have openssl");
146 assert(0);
147 #endif
148 break;
149 default:
150 assert(0);
151 break;
152 }
153 }
154 catch (Transport::Exception& )
155 {
156 ErrLog(<< "Failed to create transport: "
157 << (version == V4 ? "V4" : "V6") << " "
158 << Tuple::toData(protocol) << " " << port << " on "
159 << (ipInterface.empty() ? "ANY" : ipInterface.c_str()));
160 throw;
161 }
162 addTransport(std::auto_ptr<Transport>(transport));
163 }
164
165 void
166 SipStack::addTransport( std::auto_ptr<Transport> transport)
167 {
168 //.dcm. once addTransport starts throwing, ned to back out alias
169 if (!transport->interfaceName().empty())
170 {
171 addAlias(transport->interfaceName(), transport->port());
172 }
173 mTransactionController.transportSelector().addTransport(transport);
174 }
175
176 Fifo<TransactionMessage>&
177 SipStack::stateMacFifo()
178 {
179 return mTransactionController.transportSelector().stateMacFifo();
180 }
181
182 void
183 SipStack::addAlias(const Data& domain, int port)
184 {
185 int portToUse = (port == 0) ? Symbols::DefaultSipPort : port;
186
187 DebugLog (<< "Adding domain alias: " << domain << ":" << portToUse);
188 assert(!mShuttingDown);
189 mDomains.insert(domain + ":" + Data(portToUse));
190 }
191
192 Data
193 SipStack::getHostname()
194 {
195 // if you change this, please #def old version for windows
196 char hostName[1024];
197 int err = gethostname( hostName, sizeof(hostName) );
198 assert( err == 0 );
199
200 struct hostent* hostEnt = gethostbyname( hostName );
201 if ( !hostEnt )
202 {
203 // this can fail when there is no name server
204 // !cj! - need to decided what error to return
205 ErrLog( << "gethostbyname failed - name server is probably down" );
206 return "localhost";
207 }
208 assert( hostEnt );
209
210 struct in_addr* addr = (struct in_addr*) hostEnt->h_addr_list[0];
211 assert( addr );
212
213 // if you change this, please #def old version for windows
214 char* addrA = inet_ntoa( *addr );
215 Data ret(addrA);
216
217 Data retHost( hostEnt->h_name );
218
219 return retHost;
220 }
221
222
223 Data
224 SipStack::getHostAddress()
225 {
226 // if you change this, please #def old version for windows
227 char hostName[1024];
228 int err = gethostname( hostName, sizeof(hostName) );
229 assert( err == 0 );
230
231 struct hostent* hostEnt = gethostbyname( hostName );
232 assert( hostEnt );
233
234 struct in_addr* addr = (struct in_addr*) hostEnt->h_addr_list[0];
235 assert( addr );
236
237 // if you change this, please #def old version for windows
238 char* addrA = inet_ntoa( *addr );
239 Data ret(addrA);
240
241 //Data retHost( hostEnt->h_name );
242
243 return ret;
244 }
245
246
247 bool
248 SipStack::isMyDomain(const Data& domain, int port) const
249 {
250 return (mDomains.count(domain + ":" +
251 Data(port == 0 ? Symbols::DefaultSipPort : port)) != 0);
252 }
253
254 const Uri&
255 SipStack::getUri() const
256 {
257 if (mDomains.empty())
258 {
259 CritLog(<< "There are no associated transports");
260 throw Exception("No associated transports", __FILE__, __LINE__);
261 }
262
263 static Uri myUri("sip:" + *mDomains.begin());
264
265 return myUri;
266 }
267
268 void
269 SipStack::send(const SipMessage& msg, TransactionUser* tu)
270 {
271 DebugLog (<< "SEND: " << msg.brief());
272 //DebugLog (<< msg);
273 //assert(!mShuttingDown);
274
275 SipMessage* toSend = new SipMessage(msg);
276 if (tu)
277 {
278 toSend->setTransactionUser(tu);
279 }
280 toSend->setFromTU();
281
282 mTransactionController.send(toSend);
283 }
284
285
286 // this is only if you want to send to a destination not in the route. You
287 // probably don't want to use it.
288 void
289 SipStack::sendTo(const SipMessage& msg, const Uri& uri, TransactionUser* tu)
290 {
291 //assert(!mShuttingDown);
292
293 SipMessage* toSend = new SipMessage(msg);
294 if (tu) toSend->setTransactionUser(tu);
295 toSend->setForceTarget(uri);
296 toSend->setFromTU();
297
298 mTransactionController.send(toSend);
299 }
300
301 // this is only if you want to send to a destination not in the route. You
302 // probably don't want to use it.
303 void
304 SipStack::sendTo(const SipMessage& msg, const Tuple& destination, TransactionUser* tu)
305 {
306 assert(!mShuttingDown);
307 assert(destination.transport);
308
309 //SipMessage* toSend = new SipMessage(msg);
310 SipMessage* toSend = dynamic_cast<SipMessage*>(msg.clone());
311 if (tu) toSend->setTransactionUser(tu);
312 toSend->setDestination(destination);
313 toSend->setFromTU();
314
315 mTransactionController.send(toSend);
316 }
317
318 void
319 SipStack::checkAsyncProcessHandler()
320 {
321 if (mAsyncProcessHandler)
322 {
323 mAsyncProcessHandler->handleProcessNotification();
324 }
325 }
326
327 void
328 SipStack::post(const ApplicationMessage& message)
329 {
330 assert(!mShuttingDown);
331 Message* toPost = message.clone();
332 //mTUFifo.add(toPost, TimeLimitFifo<Message>::InternalElement);
333 mTuSelector.add(toPost, TimeLimitFifo<Message>::InternalElement);
334 }
335
336 void
337 SipStack::post(const ApplicationMessage& message, unsigned int secondsLater,
338 TransactionUser* tu)
339 {
340 assert(!mShuttingDown);
341 postMS(message, secondsLater*1000, tu);
342 }
343
344 void
345 SipStack::postMS(const ApplicationMessage& message, unsigned int ms,
346 TransactionUser* tu)
347 {
348 assert(!mShuttingDown);
349 Message* toPost = message.clone();
350 if (tu) toPost->setTransactionUser(tu);
351 Lock lock(mAppTimerMutex);
352 mAppTimers.add(Timer(ms, toPost));
353 //.dcm. timer update rather than process cycle...optimize by checking if sooner
354 //than current timeTillNextProcess?
355 checkAsyncProcessHandler();
356 }
357
358 bool
359 SipStack::hasMessage() const
360 {
361 return mTUFifo.messageAvailable();
362 }
363
364 SipMessage*
365 SipStack::receive()
366 {
367 // Check to see if a message is available and if it is return the
368 // waiting message. Otherwise, return 0
369 if (mTUFifo.messageAvailable())
370 {
371 // we should only ever have SIP messages on the TU Fifo
372 // unless we've registered for termination messages.
373 Message* msg = mTUFifo.getNext();
374 SipMessage* sip=0;
375 if ((sip=dynamic_cast<SipMessage*>(msg)))
376 {
377 DebugLog (<< "RECV: " << sip->brief());
378 return sip;
379 }
380 else
381 {
382 // assert(0); // !CJ! removed the assert - happens 1 minute after
383 // stack starts up
384 delete msg;
385 return 0;
386 }
387 }
388 else
389 {
390 return 0;
391 }
392 }
393
394 Message*
395 SipStack::receiveAny()
396 {
397 // Check to see if a message is available and if it is return the
398 // waiting message. Otherwise, return 0
399 if (mTUFifo.messageAvailable())
400 {
401 // application messages can flow through
402 Message* msg = mTUFifo.getNext();
403 SipMessage* sip=dynamic_cast<SipMessage*>(msg);
404 if (sip)
405 {
406 DebugLog (<< "RECV: " << sip->brief());
407 }
408 return msg;
409 }
410 else
411 {
412 return 0;
413 }
414 }
415
416 void
417 SipStack::process(FdSet& fdset)
418 {
419 if(!mShuttingDown)
420 {
421 RESIP_STATISTICS(mStatsManager.process());
422 }
423 mTransactionController.process(fdset);
424 mTuSelector.process();
425 mDnsStub->process(fdset);
426
427 Lock lock(mAppTimerMutex);
428 mAppTimers.process();
429 }
430
431 /// returns time in milliseconds when process next needs to be called
432 unsigned int
433 SipStack::getTimeTillNextProcessMS()
434 {
435 Lock lock(mAppTimerMutex);
436 return resipMin(mTransactionController.getTimeTillNextProcessMS(),
437 mAppTimers.msTillNextTimer());
438 }
439
440 void
441 SipStack::registerForTransactionTermination()
442 {
443 mTransactionController.registerForTransactionTermination();
444 }
445
446 void
447 SipStack::buildFdSet(FdSet& fdset)
448 {
449 mTransactionController.buildFdSet(fdset);
450 mDnsStub->buildFdSet(fdset);
451 }
452
453 Security*
454 SipStack::getSecurity() const
455 {
456 return mSecurity;
457 }
458
459 void
460 SipStack::setStatisticsInterval(unsigned long seconds)
461 {
462 mStatsManager.setInterval(seconds);
463 }
464
465 void
466 SipStack::registerTransactionUser(TransactionUser& tu)
467 {
468 mTuSelector.registerTransactionUser(tu);
469 }
470
471 void
472 SipStack::requestTransactionUserShutdown(TransactionUser& tu)
473 {
474 mTuSelector.requestTransactionUserShutdown(tu);
475 }
476
477 void
478 SipStack::unregisterTransactionUser(TransactionUser& tu)
479 {
480 mTuSelector.unregisterTransactionUser(tu);
481 }
482
483 void
484 SipStack::registerBlacklistListener(int rrType, DnsStub::BlacklistListener* listener)
485 {
486 mTransactionController.registerBlacklistListener(rrType, listener);
487 }
488
489 void
490 SipStack::unregisterBlacklistListener(int rrType, DnsStub::BlacklistListener* listener)
491 {
492 mTransactionController.unregisterBlacklistListener(rrType, listener);
493 }
494
495 DnsStub&
496 SipStack::getDnsStub() const
497 {
498 return *mDnsStub;
499 }
500
501 std::ostream&
502 SipStack::dump(std::ostream& strm) const
503 {
504 Lock lock(mAppTimerMutex);
505 strm << "SipStack: " << (this->mSecurity ? "with security " : "without security ")
506 << std::endl
507 << "domains: " << Inserter(this->mDomains)
508 << std::endl
509 << " TUFifo size=" << this->mTUFifo.size() << std::endl
510 << " Timers size=" << this->mTransactionController.mTimers.size() << std::endl
511 << " AppTimers size=" << this->mAppTimers.size() << std::endl
512 << " ServerTransactionMap size=" << this->mTransactionController.mServerTransactionMap.size() << std::endl
513 << " ClientTransactionMap size=" << this->mTransactionController.mClientTransactionMap.size() << std::endl
514 << " Exact Transports=" << Inserter(this->mTransactionController.mTransportSelector.mExactTransports) << std::endl
515 << " Any Transports=" << Inserter(this->mTransactionController.mTransportSelector.mAnyInterfaceTransports) << std::endl;
516 return strm;
517 }
518
519 std::ostream&
520 resip::operator<<(std::ostream& strm,
521 const SipStack& stack)
522 {
523 return stack.dump(strm);
524 }
525
526
527 /* ====================================================================
528 * The Vovida Software License, Version 1.0
529 *
530 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
531 *
532 * Redistribution and use in source and binary forms, with or without
533 * modification, are permitted provided that the following conditions
534 * are met:
535 *
536 * 1. Redistributions of source code must retain the above copyright
537 * notice, this list of conditions and the following disclaimer.
538 *
539 * 2. Redistributions in binary form must reproduce the above copyright
540 * notice, this list of conditions and the following disclaimer in
541 * the documentation and/or other materials provided with the
542 * distribution.
543 *
544 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
545 * and "Vovida Open Communication Application Library (VOCAL)" must
546 * not be used to endorse or promote products derived from this
547 * software without prior written permission. For written
548 * permission, please contact vocal@vovida.org.
549 *
550 * 4. Products derived from this software may not be called "VOCAL", nor
551 * may "VOCAL" appear in their name, without prior written
552 * permission of Vovida Networks, Inc.
553 *
554 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
555 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
556 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
557 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
558 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
559 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
560 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
561 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
562 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
563 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
564 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
565 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
566 * DAMAGE.
567 *
568 * ====================================================================
569 *
570 * This software consists of voluntary contributions made by Vovida
571 * Networks, Inc. and many individuals on behalf of Vovida Networks,
572 * Inc. For more information on Vovida Networks, Inc., please see
573 * <http://www.vovida.org/>.
574 *
575 */

Properties

Name Value
svn:eol-style LF

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27