/[resiprocate]/main/sip/resiprocate/dum/test/BasicCall.cxx
ViewVC logotype

Contents of /main/sip/resiprocate/dum/test/BasicCall.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4781 - (show annotations) (download)
Mon May 30 16:35:33 2005 UTC (14 years, 5 months ago) by sgodin
File size: 22409 byte(s)
modified to work with new ShartPtr management of Master/UserProfiles
1 #include "resiprocate/SdpContents.hxx"
2 #include "resiprocate/SipMessage.hxx"
3 #include "resiprocate/ShutdownMessage.hxx"
4 #include "resiprocate/SipStack.hxx"
5 #include "resiprocate/dum/ClientAuthManager.hxx"
6 #include "resiprocate/dum/ClientInviteSession.hxx"
7 #include "resiprocate/dum/ClientRegistration.hxx"
8 #include "resiprocate/dum/DialogUsageManager.hxx"
9 #include "resiprocate/dum/DumShutdownHandler.hxx"
10 #include "resiprocate/dum/InviteSessionHandler.hxx"
11 #include "resiprocate/dum/MasterProfile.hxx"
12 #include "resiprocate/dum/RegistrationHandler.hxx"
13 #include "resiprocate/dum/ServerInviteSession.hxx"
14 #include "resiprocate/dum/ServerOutOfDialogReq.hxx"
15 #include "resiprocate/dum/OutOfDialogHandler.hxx"
16 #include "resiprocate/dum/AppDialog.hxx"
17 #include "resiprocate/dum/AppDialogSet.hxx"
18 #include "resiprocate/dum/AppDialogSetFactory.hxx"
19 #include "resiprocate/os/Log.hxx"
20 #include "resiprocate/os/Logger.hxx"
21 #include "resiprocate/os/Random.hxx"
22
23 #include <sstream>
24 #include <time.h>
25
26 #define RESIPROCATE_SUBSYSTEM Subsystem::TEST
27
28 using namespace resip;
29 using namespace std;
30
31 void sleepSeconds(unsigned int seconds)
32 {
33 #ifdef WIN32
34 Sleep(seconds*1000);
35 #else
36 sleep(seconds);
37 #endif
38 }
39
40 /////////////////////////////////////////////////////////////////////////////////
41 //
42 // Classes that provide the mapping between Application Data and DUM
43 // dialogs/dialogsets
44 //
45 // The DUM layer creates an AppDialog/AppDialogSet object for inbound/outbound
46 // SIP Request that results in Dialog creation.
47 //
48 /////////////////////////////////////////////////////////////////////////////////
49 class testAppDialog : public AppDialog
50 {
51 public:
52 testAppDialog(HandleManager& ham, Data &SampleAppData) : AppDialog(ham), mSampleAppData(SampleAppData)
53 {
54 cout << mSampleAppData << ": testAppDialog: created." << endl;
55 }
56 virtual ~testAppDialog()
57 {
58 cout << mSampleAppData << ": testAppDialog: destroyed." << endl;
59 }
60 Data mSampleAppData;
61 };
62
63 class testAppDialogSet : public AppDialogSet
64 {
65 public:
66 testAppDialogSet(DialogUsageManager& dum, Data SampleAppData) : AppDialogSet(dum), mSampleAppData(SampleAppData)
67 {
68 cout << mSampleAppData << ": testAppDialogSet: created." << endl;
69 }
70 virtual ~testAppDialogSet()
71 {
72 cout << mSampleAppData << ": testAppDialogSet: destroyed." << endl;
73 }
74 virtual AppDialog* createAppDialog(const SipMessage& msg)
75 {
76 return new testAppDialog(mDum, mSampleAppData);
77 }
78 virtual SharedPtr<UserProfile>& selectUASUserProfile(const SipMessage& msg)
79 {
80 cout << mSampleAppData << ": testAppDialogSet: UAS UserProfile requested for msg: " << msg.brief() << endl;
81 return mDum.getMasterUserProfile();
82 }
83 Data mSampleAppData;
84 };
85
86 class testAppDialogSetFactory : public AppDialogSetFactory
87 {
88 public:
89 virtual AppDialogSet* createAppDialogSet(DialogUsageManager& dum, const SipMessage& msg)
90 { return new testAppDialogSet(dum, Data("UAS") + Data("(") + getMethodName(msg.header(h_RequestLine).getMethod()) + Data(")")); }
91 // For a UAS the testAppDialogSet will be created by DUM using this function. If you want to set
92 // Application Data, then one approach is to wait for onNewSession(ServerInviteSessionHandle ...)
93 // to be called, then use the ServerInviteSessionHandle to get at the AppDialogSet or AppDialog,
94 // then cast to your derived class and set the desired application data.
95 };
96
97
98 // Generic InviteSessionHandler
99 class TestInviteSessionHandler : public InviteSessionHandler, public ClientRegistrationHandler, public OutOfDialogHandler
100 {
101 public:
102 Data name;
103 bool registered;
104 ClientRegistrationHandle registerHandle;
105
106 TestInviteSessionHandler(const Data& n) : name(n), registered(false)
107 {
108 }
109
110 virtual ~TestInviteSessionHandler()
111 {
112 }
113
114 virtual void onSuccess(ClientRegistrationHandle h, const SipMessage& response)
115 {
116 registerHandle = h;
117 assert(registerHandle.isValid());
118 cout << name << ": ClientRegistration-onSuccess - " << response.brief() << endl;
119 registered = true;
120 }
121
122 virtual void onFailure(ClientRegistrationHandle, const SipMessage& msg)
123 {
124 cout << name << ": ClientRegistration-onFailure - " << msg.brief() << endl;
125 throw; // Ungracefully end
126 }
127
128 virtual void onRemoved(ClientRegistrationHandle)
129 {
130 cout << name << ": ClientRegistration-onRemoved" << endl;
131 }
132
133 virtual int onRequestRetry(ClientRegistrationHandle, int retrySeconds, const SipMessage& response)
134 {
135 cout << name << ": ClientRegistration-onRequestRetry (" << retrySeconds << ") - " << response.brief() << endl;
136 return -1;
137 }
138
139 virtual void onNewSession(ClientInviteSessionHandle, InviteSession::OfferAnswerType oat, const SipMessage& msg)
140 {
141 cout << name << ": ClientInviteSession-onNewSession - " << msg.brief() << endl;
142 }
143
144 virtual void onNewSession(ServerInviteSessionHandle, InviteSession::OfferAnswerType oat, const SipMessage& msg)
145 {
146 cout << name << ": ServerInviteSession-onNewSession - " << msg.brief() << endl;
147 }
148
149 virtual void onFailure(ClientInviteSessionHandle, const SipMessage& msg)
150 {
151 cout << name << ": ClientInviteSession-onFailure - " << msg.brief() << endl;
152 }
153
154 virtual void onProvisional(ClientInviteSessionHandle, const SipMessage& msg)
155 {
156 cout << name << ": ClientInviteSession-onProvisional - " << msg.brief() << endl;
157 }
158
159 virtual void onConnected(ClientInviteSessionHandle, const SipMessage& msg)
160 {
161 cout << name << ": ClientInviteSession-onConnected - " << msg.brief() << endl;
162 }
163
164 virtual void onStaleCallTimeout(ClientInviteSessionHandle)
165 {
166 cout << name << ": ClientInviteSession-onStaleCallTimeout" << endl;
167 }
168
169 virtual void onConnected(InviteSessionHandle, const SipMessage& msg)
170 {
171 cout << name << ": InviteSession-onConnected - " << msg.brief() << endl;
172 }
173
174 virtual void onRedirected(ClientInviteSessionHandle, const SipMessage& msg)
175 {
176 cout << name << ": ClientInviteSession-onRedirected - " << msg.brief() << endl;
177 }
178
179 virtual void onTerminated(InviteSessionHandle, InviteSessionHandler::TerminatedReason reason, const SipMessage* msg)
180 {
181 cout << name << ": InviteSession-onTerminated - " << (msg ? msg->brief() : "") << endl;
182 assert(0); // This is overrideen in UAS and UAC specific handlers
183 }
184
185 virtual void onAnswer(InviteSessionHandle, const SipMessage& msg, const SdpContents& sdp)
186 {
187 cout << name << ": InviteSession-onAnswer(SDP)" << endl;
188 //sdp->encode(cout);
189 }
190
191 virtual void onOffer(InviteSessionHandle is, const SipMessage& msg, const SdpContents& sdp)
192 {
193 cout << name << ": InviteSession-onOffer(SDP)" << endl;
194 //sdp->encode(cout);
195 }
196
197 virtual void onEarlyMedia(ClientInviteSessionHandle, const SipMessage& msg, const SdpContents& sdp)
198 {
199 cout << name << ": InviteSession-onEarlyMedia(SDP)" << endl;
200 //sdp->encode(cout);
201 }
202
203 virtual void onOfferRequired(InviteSessionHandle, const SipMessage& msg)
204 {
205 cout << name << ": InviteSession-onOfferRequired - " << msg.brief() << endl;
206 }
207
208 virtual void onOfferRejected(InviteSessionHandle, const SipMessage& msg)
209 {
210 cout << name << ": InviteSession-onOfferRejected - " << msg.brief() << endl;
211 }
212
213 virtual void onDialogModified(InviteSessionHandle, InviteSession::OfferAnswerType oat, const SipMessage& msg)
214 {
215 cout << name << ": InviteSession-onDialogModified - " << msg.brief() << endl;
216 }
217
218 virtual void onInfo(InviteSessionHandle, const SipMessage& msg)
219 {
220 cout << name << ": InviteSession-onInfo - " << msg.brief() << endl;
221 }
222
223 virtual void onRefer(InviteSessionHandle, ServerSubscriptionHandle, const SipMessage& msg)
224 {
225 cout << name << ": InviteSession-onRefer - " << msg.brief() << endl;
226 }
227
228 virtual void onReferAccepted(InviteSessionHandle, ClientSubscriptionHandle, const SipMessage& msg)
229 {
230 cout << name << ": InviteSession-onReferAccepted - " << msg.brief() << endl;
231 }
232
233 virtual void onReferRejected(InviteSessionHandle, const SipMessage& msg)
234 {
235 cout << name << ": InviteSession-onReferRejected - " << msg.brief() << endl;
236 }
237
238 virtual void onInfoSuccess(InviteSessionHandle, const SipMessage& msg)
239 {
240 cout << name << ": InviteSession-onInfoSuccess - " << msg.brief() << endl;
241 }
242
243 virtual void onInfoFailure(InviteSessionHandle, const SipMessage& msg)
244 {
245 cout << name << ": InviteSession-onInfoFailure - " << msg.brief() << endl;
246 }
247
248 virtual void onForkDestroyed(ClientInviteSessionHandle)
249 {
250 cout << name << ": ClientInviteSession-onForkDestroyed" << endl;
251 }
252
253 // Out-of-Dialog Callbacks
254 virtual void onSuccess(ClientOutOfDialogReqHandle, const SipMessage& successResponse)
255 {
256 cout << name << ": ClientOutOfDialogReq-onSuccess - " << successResponse.brief() << endl;
257 }
258 virtual void onFailure(ClientOutOfDialogReqHandle, const SipMessage& errorResponse)
259 {
260 cout << name << ": ClientOutOfDialogReq-onFailure - " << errorResponse.brief() << endl;
261 }
262 virtual void onReceivedRequest(ServerOutOfDialogReqHandle ood, const SipMessage& request)
263 {
264 cout << name << ": ServerOutOfDialogReq-onReceivedRequest - " << request.brief() << endl;
265 // Add SDP to response here if required
266 cout << name << ": Sending 200 response to OPTIONS." << endl;
267 ood->send(ood->answerOptions());
268 }
269 };
270
271 class TestUac : public TestInviteSessionHandler
272 {
273 public:
274 bool done;
275 SdpContents* sdp;
276 HeaderFieldValue* hfv;
277 Data* txt;
278
279 TestUac()
280 : TestInviteSessionHandler("UAC"),
281 done(false),
282 sdp(0),
283 hfv(0),
284 txt(0)
285 {
286 txt = new Data("v=0\r\n"
287 "o=1900 369696545 369696545 IN IP4 192.168.2.15\r\n"
288 "s=X-Lite\r\n"
289 "c=IN IP4 192.168.2.15\r\n"
290 "t=0 0\r\n"
291 "m=audio 8000 RTP/AVP 8 3 98 97 101\r\n"
292 "a=rtpmap:8 pcma/8000\r\n"
293 "a=rtpmap:3 gsm/8000\r\n"
294 "a=rtpmap:98 iLBC\r\n"
295 "a=rtpmap:97 speex/8000\r\n"
296 "a=rtpmap:101 telephone-event/8000\r\n"
297 "a=fmtp:101 0-15\r\n");
298
299 hfv = new HeaderFieldValue(txt->data(), txt->size());
300 Mime type("application", "sdp");
301 sdp = new SdpContents(hfv, type);
302 }
303
304 virtual ~TestUac()
305 {
306 delete sdp;
307 }
308
309 virtual void onTerminated(InviteSessionHandle, InviteSessionHandler::TerminatedReason reason, const SipMessage* msg)
310 {
311 cout << name << ": InviteSession-onTerminated - " << (msg ? msg->brief() : "") << endl;
312 done = true;
313 }
314 };
315
316 class TestUas : public TestInviteSessionHandler
317 {
318
319 public:
320 bool done;
321 time_t* pHangupAt;
322
323 SdpContents* sdp;
324 HeaderFieldValue* hfv;
325 Data* txt;
326
327 TestUas(time_t* pH)
328 : TestInviteSessionHandler("UAS"),
329 done(false),
330 pHangupAt(pH),
331 hfv(0)
332 {
333 pHangupAt = pHangupAt;
334
335 txt = new Data("v=0\r\n"
336 "o=1900 369696545 369696545 IN IP4 192.168.2.15\r\n"
337 "s=X-Lite\r\n"
338 "c=IN IP4 192.168.2.15\r\n"
339 "t=0 0\r\n"
340 "m=audio 8001 RTP/AVP 8 3 98 97 101\r\n"
341 "a=rtpmap:8 pcma/8000\r\n"
342 "a=rtpmap:3 gsm/8000\r\n"
343 "a=rtpmap:98 iLBC\r\n"
344 "a=rtpmap:97 speex/8000\r\n"
345 "a=rtpmap:101 telephone-event/8000\r\n"
346 "a=fmtp:101 0-15\r\n");
347
348 hfv = new HeaderFieldValue(txt->data(), txt->size());
349 Mime type("application", "sdp");
350 sdp = new SdpContents(hfv, type);
351 }
352
353 ~TestUas()
354 {
355 delete sdp;
356 }
357
358 virtual void
359 onNewSession(ServerInviteSessionHandle sis, InviteSession::OfferAnswerType oat, const SipMessage& msg)
360 {
361 cout << name << ": ServerInviteSession-onNewSession - " << msg.brief() << endl;
362 cout << name << ": Sending 180 response." << endl;
363 mSis = sis;
364 sis->provisional(180);
365 }
366
367 virtual void onTerminated(InviteSessionHandle, InviteSessionHandler::TerminatedReason reason, const SipMessage* msg)
368 {
369 cout << name << ": InviteSession-onTerminated - " << (msg ? msg->brief() : "") << endl;
370 done = true;
371 }
372
373 virtual void onOffer(InviteSessionHandle is, const SipMessage& msg, const SdpContents& sdp)
374 {
375 cout << name << ": InviteSession-onOffer(SDP)" << endl;
376 //sdp->encode(cout);
377 cout << name << ": Sending 200 response with SDP answer." << endl;
378 is->provideAnswer(sdp);
379 mSis->accept();
380 *pHangupAt = time(NULL) + 5;
381 }
382
383 // Normal people wouldn't put this functionality in the handler
384 // it's a kludge for this test for right now
385 void hangup()
386 {
387 if (mSis.isValid())
388 {
389 cout << name << ": Sending BYE." << endl;
390 mSis->end();
391 done = true;
392 }
393 }
394 private:
395 ServerInviteSessionHandle mSis;
396 };
397
398 class TestShutdownHandler : public DumShutdownHandler
399 {
400 public:
401 TestShutdownHandler(const Data& n) : name(n), dumShutDown(false) { }
402 virtual ~TestShutdownHandler(){}
403
404 Data name;
405 bool dumShutDown;
406 virtual void onDumCanBeDeleted()
407 {
408 cout << name << ": onDumCanBeDeleted." << endl;
409 dumShutDown = true;
410 }
411 };
412
413
414 #define NO_REGISTRATION 1
415 int
416 main (int argc, char** argv)
417 {
418 //Log::initialize(Log::Cout, resip::Log::Warning, argv[0]);
419 //Log::initialize(Log::Cout, resip::Log::Debug, argv[0]);
420 Log::initialize(Log::Cout, resip::Log::Info, argv[0]);
421
422 //set up UAC
423 SipStack stackUac;
424 DialogUsageManager* dumUac = new DialogUsageManager(stackUac);
425 dumUac->addTransport(UDP, 12005);
426
427 SharedPtr<MasterProfile> uacMasterProfile(new MasterProfile);
428 auto_ptr<ClientAuthManager> uacAuth(new ClientAuthManager);
429 dumUac->setMasterProfile(uacMasterProfile);
430 dumUac->setClientAuthManager(uacAuth);
431
432 TestUac uac;
433 dumUac->setInviteSessionHandler(&uac);
434 dumUac->setClientRegistrationHandler(&uac);
435 dumUac->addOutOfDialogHandler(OPTIONS, &uac);
436
437 auto_ptr<AppDialogSetFactory> uac_dsf(new testAppDialogSetFactory);
438 dumUac->setAppDialogSetFactory(uac_dsf);
439
440 #if !defined(NO_REGISTRATION)
441 //your aor, credentials, etc here
442 NameAddr uacAor("sip:101@foo.net");
443 dumUac->getMasterProfile()->addDigestCredential( "foo.net", "derek@foo.net", "pass6" );
444 dumUac->getMasterProfile()->setOutboundProxy(Uri("sip:209.134.58.33:9090"));
445 #else
446 NameAddr uacAor("sip:UAC@127.0.0.1:12005");
447 #endif
448
449 dumUac->getMasterProfile()->setDefaultFrom(uacAor);
450 dumUac->getMasterProfile()->setDefaultRegistrationTime(70);
451
452 //set up UAS
453 SipStack stackUas;
454 DialogUsageManager* dumUas = new DialogUsageManager(stackUas);
455 dumUas->addTransport(UDP, 12010);
456
457 SharedPtr<MasterProfile> uasMasterProfile(new MasterProfile);
458 std::auto_ptr<ClientAuthManager> uasAuth(new ClientAuthManager);
459 dumUas->setMasterProfile(uasMasterProfile);
460 dumUas->setClientAuthManager(uasAuth);
461
462 #if !defined(NO_REGISTRATION)
463 //your aor, credentials, etc here
464 NameAddr uasAor("sip:105@foo.net");
465 dumUas->getMasterProfile()->addDigestCredential( "foo.net", "derek@foo.net", "pass6" );
466 dumUas->getMasterProfile()->setOutboundProxy(Uri("sip:209.134.58.33:9090"));
467 #else
468 NameAddr uasAor("sip:UAS@127.0.0.1:12010");
469 #endif
470
471 dumUas->getMasterProfile()->setDefaultRegistrationTime(70);
472 dumUas->getMasterProfile()->setDefaultFrom(uasAor);
473
474 time_t bHangupAt = 0;
475 TestUas uas(&bHangupAt);
476 dumUas->setClientRegistrationHandler(&uas);
477 dumUas->setInviteSessionHandler(&uas);
478 dumUas->addOutOfDialogHandler(OPTIONS, &uas);
479
480 auto_ptr<AppDialogSetFactory> uas_dsf(new testAppDialogSetFactory);
481 dumUas->setAppDialogSetFactory(uas_dsf);
482
483 #if !defined(NO_REGISTRATION)
484 {
485 SipMessage& regMessage = dumUas->makeRegistration(uasAor, new testAppDialogSet(*dumUac, "UAS(Registration)"));
486 cout << "Sending register for Uas: " << endl << regMessage << endl;
487 dumUas->send(regMessage);
488 }
489 {
490 SipMessage& regMessage = dumUac->makeRegistration(uacAor, new testAppDialogSet(*dumUac, "UAS(Registration)"));
491 cout << "Sending register for Uac: " << endl << regMessage << endl;
492 dumUac->send(regMessage);
493 }
494 #else
495 uac.registered = true;
496 uas.registered = true;
497 #endif
498
499 bool finishedTest = false;
500 bool stoppedRegistering = false;
501 bool startedCallFlow = false;
502 bool hungup = false;
503 TestShutdownHandler uasShutdownHandler("UAS");
504 TestShutdownHandler uacShutdownHandler("UAC");
505
506 while (!(uasShutdownHandler.dumShutDown && uacShutdownHandler.dumShutDown))
507 {
508 if (!uacShutdownHandler.dumShutDown)
509 {
510 FdSet fdset;
511 stackUac.buildFdSet(fdset);
512 int err = fdset.selectMilliSeconds(resipMin((int)stackUac.getTimeTillNextProcessMS(), 50));
513 assert ( err != -1 );
514 stackUac.process(fdset);
515 while(dumUac->process());
516 }
517 if (!uasShutdownHandler.dumShutDown)
518 {
519 FdSet fdset;
520 stackUas.buildFdSet(fdset);
521 int err = fdset.selectMilliSeconds(resipMin((int)stackUas.getTimeTillNextProcessMS(), 50));
522 assert ( err != -1 );
523 stackUas.process(fdset);
524 while(dumUas->process());
525 }
526
527 if (!(uas.done && uac.done))
528 {
529 if (uas.registered && uac.registered && !startedCallFlow)
530 {
531 if (!startedCallFlow)
532 {
533 startedCallFlow = true;
534 #if !defined(NO_REGISTRATION)
535 cout << "!!!!!!!!!!!!!!!! Registered !!!!!!!!!!!!!!!! " << endl;
536 #endif
537
538 // Kick off call flow by sending an OPTIONS request then an INVITE request from the UAC to the UAS
539 cout << "UAC: Sending Options Request to UAS." << endl;
540 dumUac->send(dumUac->makeOutOfDialogRequest(uasAor, OPTIONS, new testAppDialogSet(*dumUac, "UAC(OPTIONS)"))); // Should probably add Allow, Accept, Accept-Encoding, Accept-Language and Supported headers - but this is fine for testing/demonstration
541
542 cout << "UAC: Sending Invite Request to UAS." << endl;
543 dumUac->send(dumUac->makeInviteSession(uasAor, uac.sdp, new testAppDialogSet(*dumUac, "UAC(INVITE)")));
544 }
545 }
546
547 // Check if we should hangup yet
548 if (bHangupAt!=0)
549 {
550 if (time(NULL)>bHangupAt && !hungup)
551 {
552 hungup = true;
553 uas.hangup();
554 }
555 }
556 }
557 else
558 {
559 if (!stoppedRegistering)
560 {
561 finishedTest = true;
562 stoppedRegistering = true;
563 dumUas->shutdown(&uasShutdownHandler);
564 dumUac->shutdown(&uacShutdownHandler);
565 #if !defined(NO_REGISTRATION)
566 uas.registerHandle->stopRegistering();
567 uac.registerHandle->stopRegistering();
568 #endif
569 }
570 }
571 }
572
573 // OK to delete DUM objects now
574 delete dumUac;
575 delete dumUas;
576
577 cout << "!!!!!!!!!!!!!!!!!! Successful !!!!!!!!!! " << endl;
578 }
579
580 /* ====================================================================
581 * The Vovida Software License, Version 1.0
582 *
583 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
584 *
585 * Redistribution and use in source and binary forms, with or without
586 * modification, are permitted provided that the following conditions
587 * are met:
588 *
589 * 1. Redistributions of source code must retain the above copyright
590 * notice, this list of conditions and the following disclaimer.
591 *
592 * 2. Redistributions in binary form must reproduce the above copyright
593 * notice, this list of conditions and the following disclaimer in
594 * the documentation and/or other materials provided with the
595 * distribution.
596 *
597 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
598 * and "Vovida Open Communication Application Library (VOCAL)" must
599 * not be used to endorse or promote products derived from this
600 * software without prior written permission. For written
601 * permission, please contact vocal@vovida.org.
602 *
603 * 4. Products derived from this software may not be called "VOCAL", nor
604 * may "VOCAL" appear in their name, without prior written
605 * permission of Vovida Networks, Inc.
606 *
607 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
608 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
609 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
610 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
611 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
612 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
613 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
614 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
615 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
616 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
617 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
618 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
619 * DAMAGE.
620 *
621 * ====================================================================
622 *
623 * This software consists of voluntary contributions made by Vovida
624 * Networks, Inc. and many individuals on behalf of Vovida Networks,
625 * Inc. For more information on Vovida Networks, Inc., please see
626 * <http://www.vovida.org/>.
627 *
628 */

Properties

Name Value
svn:eol-style LF

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27