/[resiprocate]/main/resip/stack/test/testStack.cxx
ViewVC logotype

Contents of /main/resip/stack/test/testStack.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11000 - (show annotations) (download)
Sun Feb 23 21:19:19 2014 UTC (5 years, 8 months ago) by sgodin
File MIME type: text/plain
File size: 27712 byte(s)
-use new resip::sleepMs API in testStack 
1 #if defined(HAVE_CONFIG_H)
2 #include "config.h"
3 #endif
4
5 #if defined (HAVE_POPT_H)
6 #include <popt.h>
7 #else
8 #ifndef WIN32
9 #warning "will not work very well without libpopt"
10 #endif
11 #endif
12
13 #include <sys/types.h>
14 #include <iostream>
15 #include <memory>
16
17 #include "rutil/GeneralCongestionManager.hxx"
18 #include "rutil/DnsUtil.hxx"
19 #include "rutil/Inserter.hxx"
20 #include "rutil/Logger.hxx"
21 #include "resip/stack/DeprecatedDialog.hxx"
22 #include "resip/stack/Helper.hxx"
23 #include "resip/stack/SipMessage.hxx"
24 #include "resip/stack/SipStack.hxx"
25 #include "resip/stack/StackThread.hxx"
26 #include "rutil/SelectInterruptor.hxx"
27 #include "resip/stack/TransportThread.hxx"
28 #include "resip/stack/InterruptableStackThread.hxx"
29 #include "resip/stack/EventStackThread.hxx"
30 #include "resip/stack/Uri.hxx"
31
32 using namespace resip;
33 using namespace std;
34
35 #define RESIPROCATE_SUBSYSTEM Subsystem::TEST
36
37 /************************************************************************
38
39 This application tests the core resip stack as a whole. It does
40 this by creating two instances of SipStack, and sending messages
41 (transactions) between them.
42
43 Resiprocate is designed to support a variety of threading modeling
44 and event handling models (e.g., select, poll, epoll system calls),
45 and this test application can excercise various combinations.
46
47 =============================================
48 Options: --thread-type, --seltime, --intepoll
49 The various permutations and are controlled via the --thread-type
50 option. Note that because this test application runs two stacks, its
51 threading models are unusual, and not a good template for a "normal"
52 application.
53
54 The default thread-type is now "event" to better model "typical"
55 applications. The old behavior (pre-2011) can be obtained with
56 "--thread-type=common"; this is useful for debugging stack internal
57 issues since fewer threads running around.
58
59 Values are:
60
61 none Everything (both stacks and test application) run in same
62 thread. App block for time specified by --seltime each
63 message cycle. This defaults to zero, meaning app will
64 loop without every waiting, looking for any work to do.
65 When non-zero, app will wait this before checking queues.
66 Because of the endless spinning checking for work to do,
67 this mode is not useful for profiling.
68
69 common Like "none", everything (both stacks and test application)
70 run in same thread. Thread blocks until something to do,
71 and stacks will be configured to break the wait loop
72 when there is something for app to do. This avoids the
73 endless spinning of "none", and is useful for profiling.
74
75 std Each stack runs in its own thread, and that thread is
76 a "standard" select-based thread. This mode is now obsolete.
77
78 intr Each stack runs in its own thread, and that thread
79 is an interruptable select-based thread. Here, interruptable
80 means that when the app gives the thread work to do, it will
81 immediate wake up and do it, instead of waiting for
82 the select interval to expire. This mode is now obsolete.
83
84 event Each stack runs in its own thread, and that thread
85 is an interruptable event-loop based thread. The specific
86 type of event-loop depends upon the underlying platform
87 and how you compiled the stack.
88
89 epoll Like "event", but specifically uses the epoll implmentation.
90
91 fdset Like "event", but specifically uses the FdSet/select
92 implmentation.
93
94 ===============
95 Option: --bind
96 The test application creates two stack and sends messages (requests
97 and responses) between them using UDP or TCP transports. The --bind
98 option controls where the UAS side is listening. This defaults to
99 "127.0.0.1"; we use this as default because it avoids any dependency on DNS.
100
101 If DNS is working on your system, then you can set this to the DNS name
102 of one of your interfaces. Or you can use --bind=='' and we'll try
103 to figure out your local DNS name.
104
105
106 ************************************************************************/
107
108 class SharedAsyncNotify : public AsyncProcessHandler
109 {
110 public:
111 SharedAsyncNotify() { };
112 virtual ~SharedAsyncNotify() { };
113
114 virtual void handleProcessNotification();
115
116 bool waitNotify(int ms);
117
118 protected:
119 Mutex mMutex;
120 Condition mCondition;
121 };
122
123 void
124 SharedAsyncNotify::handleProcessNotification()
125 {
126 Lock lock(mMutex); (void)lock;
127 mCondition.signal();
128 }
129
130 /**
131 {ms}<0 -> wait forever
132 {ms}=0 -> don't wait
133 {ms}>0 -> Wait this many ms
134 Returns true if condition was signalled (false if timer
135 or other interrupt)
136 **/
137 bool
138 SharedAsyncNotify::waitNotify(int ms)
139 {
140 Lock lock(mMutex); (void)lock;
141
142 if (ms<0)
143 {
144 mCondition.wait(mMutex);
145 return true;
146 }
147 else
148 {
149 return mCondition.wait(mMutex, ms);
150 }
151 }
152
153 class SipStackAndThread
154 {
155 public:
156 SipStackAndThread(const char *tType,
157 AsyncProcessHandler *notifyDn=0,
158 AsyncProcessHandler *notifyUp=0);
159 ~SipStackAndThread() {
160 destroy();
161 }
162
163 SipStack& getStack() const { assert(mStack); return *mStack; }
164
165 // I don't know if these are such a good idea
166 SipStack& operator*() const { assert(mStack); return *mStack; }
167 SipStack* operator->() const { return mStack; }
168
169 void setCongestionManager(CongestionManager* cm)
170 {
171 mStack->setCongestionManager(cm);
172 }
173
174 void run()
175 {
176 if ( mThread ) mThread->run();
177 if ( mMultiThreadedStack ) mStack->run();
178 }
179 void shutdown()
180 {
181 if ( mThread ) mThread->shutdown();
182 }
183 void join()
184 {
185 if ( mThread ) mThread->join();
186 if ( mMultiThreadedStack ) mStack->shutdownAndJoinThreads();
187 }
188
189 void destroy();
190
191 // dis-allowed by not-implemented
192 SipStackAndThread& operator=(SipStackAndThread&);
193
194 protected:
195
196 SipStack *mStack;
197 ThreadIf *mThread;
198 SelectInterruptor *mSelIntr;
199 FdPollGrp *mPollGrp;
200 EventThreadInterruptor *mEventIntr;
201 bool mMultiThreadedStack;
202 };
203
204
205 SipStackAndThread::SipStackAndThread(const char *tType,
206 AsyncProcessHandler *notifyDn, AsyncProcessHandler *notifyUp)
207 : mStack(0),
208 mThread(0),
209 mSelIntr(0),
210 mPollGrp(0),
211 mEventIntr(0),
212 mMultiThreadedStack(false)
213 {
214 bool doStd = false;
215
216 assert( tType );
217
218 if (strcmp(tType,"intr")==0)
219 {
220 mSelIntr = new SelectInterruptor();
221 }
222 else if ( strcmp(tType,"event")==0
223 || strcmp(tType,"epoll")==0
224 || strcmp(tType,"fdset")==0
225 || strcmp(tType,"poll")==0 )
226 {
227 mPollGrp = FdPollGrp::create(tType);
228 mEventIntr = new EventThreadInterruptor(*mPollGrp);
229 }
230 else if ( strcmp(tType,"std")==0 )
231 {
232 doStd = true;
233 }
234 else if ( strcmp(tType,"none")==0 )
235 {
236 }
237 else if ( strcmp(tType,"multithreadedstack")==0 )
238 {
239 mMultiThreadedStack=true;
240 mPollGrp = FdPollGrp::create("event");
241 mEventIntr = new EventThreadInterruptor(*mPollGrp);
242 }
243 else
244 {
245 CritLog(<<"Bad thread-type: "<<tType);
246 exit(1);
247 }
248 SipStackOptions options;
249 options.mAsyncProcessHandler = mEventIntr?mEventIntr
250 :(mSelIntr?mSelIntr:notifyDn);
251 options.mPollGrp = mPollGrp;
252 mStack = new SipStack(options);
253
254 mStack->setFallbackPostNotify(notifyUp);
255 if (mEventIntr)
256 {
257 mThread = new EventStackThread(*mStack, *mEventIntr, *mPollGrp);
258 }
259 else
260 if (mSelIntr)
261 {
262 mThread = new InterruptableStackThread(*mStack, *mSelIntr);
263 }
264 else if (doStd)
265 {
266 mThread = new StackThread(*mStack);
267 }
268 }
269
270 void
271 SipStackAndThread::destroy()
272 {
273 if ( mThread )
274 {
275 delete mThread;
276 mThread = 0;
277 }
278 if ( mStack )
279 {
280 delete mStack;
281 mStack = 0;
282 }
283 if ( mSelIntr )
284 {
285 delete mSelIntr;
286 mSelIntr = 0;
287 }
288 if ( mEventIntr )
289 {
290 delete mEventIntr;
291 mEventIntr = 0;
292 }
293 if ( mPollGrp )
294 {
295 delete mPollGrp;
296 mPollGrp = 0;
297 }
298 }
299
300 static void
301 waitForTwoStacks(SipStackAndThread& receiver, SipStackAndThread& sender,
302 SelectInterruptor *commonIntr, int& thisseltime, bool& isStrange)
303 {
304 FdSet fdset;
305 receiver->buildFdSet(fdset);
306 sender->buildFdSet(fdset);
307 if ( commonIntr )
308 {
309 commonIntr->buildFdSet(fdset);
310 }
311
312 if ( thisseltime > 0 )
313 {
314 unsigned int stackMs = resipMin(
315 receiver->getTimeTillNextProcessMS(),
316 sender->getTimeTillNextProcessMS());
317 thisseltime = resipMin((unsigned)thisseltime, stackMs);
318 }
319 int numReady = fdset.selectMilliSeconds(thisseltime);
320
321 isStrange = (thisseltime > 4000 && numReady==0);
322 if ( commonIntr )
323 {
324 commonIntr->process(fdset);
325 }
326 receiver->process(fdset);
327 sender->process(fdset);
328 }
329
330 struct StackThreadPair
331 {
332 StackThreadPair(SipStackAndThread& receiver,
333 SipStackAndThread& sender, SharedAsyncNotify& sharedUp)
334 : mReceiver(receiver), mSender(sender), mSharedUp(sharedUp),
335 mSeltime(0), mNoStackThread(false), mCommonIntr(0)
336 {
337 }
338
339 bool wait(int& thisseltime);
340
341 SipStackAndThread& mReceiver;
342 SipStackAndThread& mSender;
343 SharedAsyncNotify& mSharedUp;
344 int mSeltime;
345 bool mNoStackThread;
346 SelectInterruptor *mCommonIntr;
347 };
348
349 bool
350 StackThreadPair::wait(int& thisseltime)
351 {
352 if(mReceiver.getStack().hasMessage() || mSender.getStack().hasMessage())
353 {
354 return false;
355 }
356
357 thisseltime = mSeltime;
358 bool isStrange = false;
359 if ( mNoStackThread )
360 {
361 // handles 'none' and 'common' thread-type
362 // if none, then commonIntr will be NULL
363 waitForTwoStacks( mReceiver, mSender, mCommonIntr, thisseltime, isStrange);
364 }
365 else
366 {
367 thisseltime = 4000;
368 bool gotPost = mSharedUp.waitNotify(thisseltime);
369 isStrange = !gotPost;
370 }
371 return isStrange;
372 }
373
374
375 static void
376 performTest(int verbose, int runs, int window, int invite,
377 Data& bindIfAddr,
378 int numPorts, int senderPort, int registrarPort, const char *proto,
379 int sendSleepMs,
380 StackThreadPair& pair)
381 {
382 NameAddr target;
383 target.uri().scheme() = "sip";
384 target.uri().user() = "fluffy";
385 target.uri().host() = bindIfAddr;
386 target.uri().port() = registrarPort;
387 target.uri().param(p_transport) = proto;
388
389 NameAddr contact;
390 contact.uri().scheme() = "sip";
391 contact.uri().user() = "fluffy";
392
393 NameAddr from = target;
394 from.uri().port() = senderPort;
395
396 UInt64 startTime = Timer::getTimeMs();
397 int outstanding=0;
398 int count = 0;
399 int sent = 0;
400
401 int rxReqTryCnt = 0, rxReqHitCnt = 0;
402 int rxRspTryCnt = 0, rxRspHitCnt = 0;
403
404 while (count < runs)
405 {
406 //InfoLog (<< "count=" << count << " messages=" << messages.size());
407
408 // load up the send window
409 for (int i=0; i<64 && sent < runs && outstanding < window; ++i)
410 {
411 DebugLog (<< "Sending " << count << " / " << runs << " (" << outstanding << ")");
412 target.uri().port() = registrarPort + (sent%numPorts);
413
414 SipMessage* next=0;
415 if (invite)
416 {
417 next = Helper::makeInvite( target, from, contact);
418 }
419 else
420 {
421 next = Helper::makeRegister( target, from, contact);
422 }
423
424 // The Via header serves two purposes:
425 // (1) tells the recipient where to send the response,
426 // (2) selects which Transport we send from
427 if (!bindIfAddr.empty() && numPorts > 1)
428 {
429 // currently TCP only honors Via if host is populated
430 // the "numPorts>1" test is for backwards compat
431 next->header(h_Vias).front().sentHost() = bindIfAddr;
432 }
433 next->header(h_Vias).front().sentPort() = senderPort + (sent%numPorts);
434 pair.mSender->send(std::auto_ptr<SipMessage>(next));
435 next = 0; // DON'T delete next; consumed by send above
436 outstanding++;
437 sent++;
438 if (sendSleepMs>0)
439 {
440 sleepMs(sendSleepMs);
441 }
442 }
443
444 int thisseltime = 0;
445 bool isStrange = pair.wait(thisseltime);
446 if (isStrange)
447 {
448 cout << "STRANGE: Stuck for long time: "
449 <<" sent="<<sent
450 <<" done="<<count
451 <<" thisseltime="<<thisseltime
452 <<endl;
453 }
454
455 for (int i=0;i<64;++i)
456 {
457 static NameAddr contact;
458
459 ++rxReqTryCnt;
460 SipMessage* request = pair.mReceiver->receive();
461 if (request==NULL)
462 break;
463 ++rxReqHitCnt;
464 assert(request->isRequest());
465 SipMessage response;
466 switch (request->header(h_RequestLine).getMethod())
467 {
468 case INVITE:
469 {
470 DeprecatedDialog dlg(contact);
471 dlg.makeResponse(*request, response, 180);
472 pair.mReceiver->send(response);
473 dlg.makeResponse(*request, response, 200);
474 pair.mReceiver->send(response);
475 break;
476 }
477
478 case ACK:
479 break;
480
481 case BYE:
482 Helper::makeResponse(response, *request, 200);
483 pair.mReceiver->send(response);
484 break;
485
486 case REGISTER:
487 Helper::makeResponse(response, *request, 200);
488 pair.mReceiver->send(response);
489 break;
490 default:
491 assert(0);
492 break;
493 }
494 delete request;
495 }
496
497 for (int i=0;i<64;++i)
498 {
499 ++rxRspTryCnt;
500 SipMessage* response = pair.mSender->receive();
501 if (response==NULL)
502 break;
503 ++rxRspHitCnt;
504 assert(response->isResponse());
505 switch(response->header(h_CSeq).method())
506 {
507 case REGISTER:
508 outstanding--;
509 if (response->header(h_StatusLine).statusCode() == 200)
510 {
511 count++;
512 }
513 else
514 {
515 --sent;
516 }
517 break;
518
519 case INVITE:
520 if (response->header(h_StatusLine).statusCode() == 200)
521 {
522 outstanding--;
523 count++;
524
525 DeprecatedDialog dlg(contact);
526 dlg.createDialogAsUAC(*response);
527 SipMessage* ack = dlg.makeAck();
528 pair.mSender->send(*ack);
529 delete ack;
530
531 SipMessage* bye = dlg.makeBye();
532 pair.mSender->send(*bye);
533 delete bye;
534 }
535 break;
536
537 case BYE:
538 break;
539
540 default:
541 assert(0);
542 break;
543 }
544
545 delete response;
546 }
547 }
548 InfoLog (<< "Finished " << count << " runs");
549
550 UInt64 elapsed = Timer::getTimeMs() - startTime;
551 if (!invite)
552 {
553 cout << runs << " registrations performed in " << elapsed << " ms, a rate of "
554 << runs / ((float) elapsed / 1000.0) << " transactions per second." << endl;
555 }
556 else
557 {
558 cout << runs << " calls performed in " << elapsed << " ms, a rate of "
559 << runs / ((float) elapsed / 1000.0) << " calls per second." << endl;
560 }
561 if ( verbose )
562 {
563 cout << "Note: this test runs both sides (client and server)" << endl;
564
565 cout << "RxCnts: "
566 <<" Req="<<rxReqHitCnt<<"/"<<rxReqTryCnt
567 <<" ("<<(rxReqHitCnt*100/rxReqTryCnt)<<"%)"
568 <<" Rsp="<<rxRspHitCnt<<"/"<<rxRspTryCnt
569 <<" ("<<(rxRspHitCnt*100/rxRspTryCnt)<<"%)"
570 << endl;
571 }
572 }
573
574 int
575 main(int argc, char* argv[])
576 {
577
578 const char* logType = "cout";
579 const char* logLevel = "WARNING";
580 const char* proto = "tcp";
581 const char* bindAddr = "127.0.0.1";
582 int doListen = 1;
583
584 int verbose = 0;
585 int runs = 10000;
586 int window = 100;
587 int seltime = 0;
588 int v6 = 0;
589 int invite=0;
590 int numPorts = 1;
591 int portBase = 0;
592 const char* threadType = "event";
593 int tpFlags = 0;
594 int sendSleepMs = 0;
595 int cManager=0;
596 int statisticsInterval=60;
597
598 #if defined(HAVE_POPT_H)
599
600 char threadTypeDesc[200];
601 strcpy(threadTypeDesc, "none|common|std|intr|multithreadedstack|");
602 strcat(threadTypeDesc, FdPollGrp::getImplList());
603
604 struct poptOption table[] = {
605 {"log-type", 'l', POPT_ARG_STRING, &logType, 0, "where to send logging messages", "syslog|cerr|cout"},
606 {"log-level", 'v', POPT_ARG_STRING, &logLevel, 0, "specify the default log level", "DEBUG|INFO|WARNING|ALERT"},
607 {"num-runs", 'r', POPT_ARG_INT, &runs, 0, "number of runs (SIP requests) in test", 0},
608 {"window-size", 'w', POPT_ARG_INT, &window, 0, "number of concurrent transactions", 0},
609 {"select-time", 's', POPT_ARG_INT, &seltime, 0, "polling interval (ms) for stack thread", 0},
610 {"protocol", 'p', POPT_ARG_STRING, &proto, 0, "protocol to use (tcp | udp)", 0},
611 {"bind", 'b', POPT_ARG_STRING, &bindAddr, 0, "interface address to bind to",0},
612 {"listen", 0, POPT_ARG_INT, &doListen, 0, "do not bind/listen sender ports", 0},
613 {"verbose", 0, POPT_ARG_INT, &verbose, 0, "verbose", 0},
614 {"v6", '6', POPT_ARG_NONE, &v6 , 0, "ipv6", 0},
615 {"invite", 'i', POPT_ARG_NONE, &invite , 0, "send INVITE/BYE instead of REGISTER", 0},
616 {"port", 0, POPT_ARG_INT, &portBase, 0, "first port to use", 0},
617 {"numports", 'n', POPT_ARG_INT, &numPorts, 0, "number of parallel sessions(ports)", 0},
618 {"thread-type", 't', POPT_ARG_STRING, &threadType,0, "stack thread type", threadTypeDesc},
619 {"tf", 0, POPT_ARG_INT, &tpFlags, 0, "bit encoding of transportFlags", 0},
620 {"sleep", 0, POPT_ARG_INT, &sendSleepMs,0, "time (ms) to sleep after each sent request", 0},
621 {"use-congestion-manager",0, POPT_ARG_NONE, &cManager , 0, "use a CongestionManager", 0},
622 {"statistics-interval", 0, POPT_ARG_INT, &statisticsInterval,0, "time in seconds between statistics logging", 0},
623 POPT_AUTOHELP
624 { NULL, 0, 0, NULL, 0 }
625 };
626
627 poptContext context = poptGetContext(NULL, argc, const_cast<const char**>(argv), table, 0);
628 int pret=poptGetNextOpt(context);
629 assert(pret==-1);
630 assert( poptGetArg(context)==NULL);
631 #endif // popt
632 Log::initialize(logType, logLevel, argv[0]);
633
634 Data bindIfAddr(bindAddr);
635 if ( bindIfAddr.size()==0 )
636 {
637 bindIfAddr = DnsUtil::getLocalHostName();
638 }
639
640 cout << "Performing " << runs << " runs with"
641 <<" win="<<window
642 <<" ip"<<(v6?"v4":"v4")
643 <<" proto="<<proto
644 <<" numports="<<numPorts
645 <<" thread="<<threadType
646 <<" bindIf="<<bindIfAddr
647 <<" listen="<<doListen
648 <<" tf="<<tpFlags
649 <<"." << endl;
650
651 const char *eachThreadType = threadType;
652 SelectInterruptor *commonIntr = NULL;
653 AsyncProcessHandler *notifyUp = NULL;
654 bool noStackThread = false;
655 SharedAsyncNotify sharedUp;
656 if ( strcmp(eachThreadType,"none")==0 )
657 {
658 // Everything runs in single thread,
659 // and we spin, just keep cycling thru looking for stuff to do.
660 // Default seltime is zero, so no delay at all. This isn't
661 // very useful for profiling because we spend all our time checking
662 // stuff to do.
663 noStackThread = true;
664 }
665 else if ( strcmp(eachThreadType,"common")==0 )
666 {
667 // Everything runs in single thread, but thread blocks
668 // until there is something to do. When there is something
669 // to do within the stack (notifyDn) or app (notifyUp) the
670 // common interruptor is invoked and it breaks the select loop.
671 seltime = 10*1000;
672 commonIntr = new SelectInterruptor();
673 notifyUp = commonIntr;
674 noStackThread = true;
675 eachThreadType = "none";
676 }
677 else
678 {
679 notifyUp = &sharedUp;
680 }
681 SipStackAndThread receiver(eachThreadType, commonIntr, notifyUp);
682 SipStackAndThread sender(eachThreadType, commonIntr, notifyUp);
683 receiver.getStack().setStatisticsInterval(statisticsInterval);
684 sender.getStack().setStatisticsInterval(statisticsInterval);
685
686 IpVersion version = (v6 ? V6 : V4);
687
688 // estimate number of sockets we need:
689 // 2x for sender and receiver
690 // 3 for UDP (listen + select interruptor)
691 // 4 for TCP (listen + connection + select interruptor)
692 // ~30 for misc (DNS, SelectInterruptors)
693 int needFds = numPorts * 14 + 30;
694 increaseLimitFds(needFds);
695
696 /* On linux, the client TCP connection port range is controll by
697 * /proc/sys/net/ipv4/ip_local_port_range, and defaults to [32768,61000].
698 * To avoid conflicts when binding, the bound ports below should
699 * stay out of the range (e.g., below 32768)
700 */
701
702
703 int senderPort = portBase;
704 if ( senderPort==0 )
705 {
706 senderPort = numPorts==1 ? 25060+(rand()&0x0fff) : 11000;
707 }
708 int registrarPort = senderPort + numPorts;
709
710 int idx;
711 std::vector<Transport*> transports;
712 for (idx=0; idx < numPorts; idx++)
713 {
714 transports.push_back(sender->addTransport(UDP,
715 senderPort+idx,
716 version,
717 StunDisabled,
718 bindIfAddr,
719 /*sipDomain*/Data::Empty,
720 /*keypass*/Data::Empty,
721 SecurityTypes::TLSv1,
722 tpFlags));
723
724 // NOBIND doesn't make sense for UDP
725 transports.push_back(sender->addTransport(TCP,
726 senderPort+idx,
727 version,
728 StunDisabled,
729 bindIfAddr,
730 /*sipDomain*/Data::Empty,
731 /*keypass*/Data::Empty,
732 SecurityTypes::TLSv1,
733 tpFlags|(doListen?0:RESIP_TRANSPORT_FLAG_NOBIND)));
734
735 // NOTE: we could also bind receive to bindIfAddr, but existing code
736 // doesn't do this. Responses are sent from here, so why don't we?
737 transports.push_back(receiver->addTransport(UDP,
738 registrarPort+idx,
739 version,
740 StunDisabled,
741 /*ipInterface*/Data::Empty,
742 /*sipDomain*/Data::Empty,
743 /*keypass*/Data::Empty,
744 SecurityTypes::TLSv1,
745 tpFlags));
746
747 transports.push_back(receiver->addTransport(TCP,
748 registrarPort+idx,
749 version,
750 StunDisabled,
751 /*ipInterface*/Data::Empty,
752 /*sipDomain*/Data::Empty,
753 /*keypass*/Data::Empty,
754 SecurityTypes::TLSv1,
755 tpFlags));
756 }
757
758 std::auto_ptr<CongestionManager> senderCongestionManager;
759 std::auto_ptr<CongestionManager> receiverCongestionManager;
760 if(cManager)
761 {
762 senderCongestionManager.reset(new GeneralCongestionManager(
763 GeneralCongestionManager::WAIT_TIME,
764 200));
765 receiverCongestionManager.reset(new GeneralCongestionManager(
766 GeneralCongestionManager::WAIT_TIME,
767 200));
768 sender.setCongestionManager(senderCongestionManager.get());
769 receiver.setCongestionManager(receiverCongestionManager.get());
770 }
771
772 std::vector<TransportThread*> transportThreads;
773 if(tpFlags & RESIP_TRANSPORT_FLAG_OWNTHREAD)
774 {
775 while(!transports.empty())
776 {
777 transportThreads.push_back(new TransportThread(*transports.back()));
778 transportThreads.back()->run();
779 transports.pop_back();
780 }
781 }
782
783 sender.run();
784 receiver.run();
785
786 StackThreadPair pair(receiver, sender, sharedUp);
787 pair.mSeltime = seltime;
788 pair.mCommonIntr = commonIntr;
789 pair.mNoStackThread = noStackThread;
790
791 performTest(verbose, runs, window, invite,
792 bindIfAddr, numPorts, senderPort, registrarPort, proto,
793 sendSleepMs, pair);
794
795 sender.shutdown();
796 receiver.shutdown();
797
798 sender.join();
799 receiver.join();
800
801 sender.setCongestionManager(0);
802 receiver.setCongestionManager(0);
803
804 if(tpFlags&RESIP_TRANSPORT_FLAG_OWNTHREAD)
805 {
806 while(!transportThreads.empty())
807 {
808 transportThreads.back()->shutdown();
809 transportThreads.back()->join();
810 delete transportThreads.back();
811 transportThreads.pop_back();
812 }
813 }
814
815 sender.destroy();
816 receiver.destroy();
817
818 if ( commonIntr )
819 {
820 delete commonIntr;
821 commonIntr = NULL;
822 }
823
824 #if defined(HAVE_POPT_H)
825 poptFreeContext(context);
826 #endif
827 return 0;
828 }
829 /* ====================================================================
830 * The Vovida Software License, Version 1.0
831 *
832 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
833 *
834 * Redistribution and use in source and binary forms, with or without
835 * modification, are permitted provided that the following conditions
836 * are met:
837 *
838 * 1. Redistributions of source code must retain the above copyright
839 * notice, this list of conditions and the following disclaimer.
840 *
841 * 2. Redistributions in binary form must reproduce the above copyright
842 * notice, this list of conditions and the following disclaimer in
843 * the documentation and/or other materials provided with the
844 * distribution.
845 *
846 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
847 * and "Vovida Open Communication Application Library (VOCAL)" must
848 * not be used to endorse or promote products derived from this
849 * software without prior written permission. For written
850 * permission, please contact vocal@vovida.org.
851 *
852 * 4. Products derived from this software may not be called "VOCAL", nor
853 * may "VOCAL" appear in their name, without prior written
854 * permission of Vovida Networks, Inc.
855 *
856 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
857 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
858 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
859 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
860 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
861 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
862 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
863 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
864 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
865 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
866 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
867 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
868 * DAMAGE.
869 *
870 * ====================================================================
871 *
872 * This software consists of voluntary contributions made by Vovida
873 * Networks, Inc. and many individuals on behalf of Vovida Networks,
874 * Inc. For more information on Vovida Networks, Inc., please see
875 * <http://www.vovida.org/>.
876 *
877 * vi: set shiftwidth=3 expandtab:
878 */

Properties

Name Value
svn:eol-style native
svn:mime-type text/plain

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27