reSIProcate/DialogUsageManager  9694
basicClientUserAgent.cxx
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include "config.h"
00003 #endif
00004 
00005 #include <rutil/Log.hxx>
00006 #include <rutil/Logger.hxx>
00007 #include <rutil/DnsUtil.hxx>
00008 #include <rutil/MD5Stream.hxx>
00009 #include <resip/stack/SdpContents.hxx>
00010 #include <resip/stack/PlainContents.hxx>
00011 #include <resip/stack/ConnectionTerminated.hxx>
00012 #include <resip/stack/Helper.hxx>
00013 #include <resip/dum/AppDialogSetFactory.hxx>
00014 #include <resip/dum/ClientAuthManager.hxx>
00015 #include <resip/dum/KeepAliveManager.hxx>
00016 #include <resip/dum/ClientInviteSession.hxx>
00017 #include <resip/dum/ServerInviteSession.hxx>
00018 #include <resip/dum/ClientSubscription.hxx>
00019 #include <resip/dum/ServerSubscription.hxx>
00020 #include <resip/dum/ClientRegistration.hxx>
00021 #include <resip/dum/ServerRegistration.hxx>
00022 #include <resip/dum/ServerOutOfDialogReq.hxx>
00023 #include <rutil/dns/AresDns.hxx>
00024 
00025 #if defined (USE_SSL)
00026 #if defined(WIN32) 
00027 #include "resip/stack/ssl/WinSecurity.hxx"
00028 #else
00029 #include "resip/stack/ssl/Security.hxx"
00030 #endif
00031 #endif
00032 
00033 #include "basicClientUserAgent.hxx"
00034 #include "basicClientCall.hxx"
00035 
00036 using namespace resip;
00037 using namespace std;
00038 
00039 #define RESIPROCATE_SUBSYSTEM Subsystem::TEST
00040 
00041 static unsigned int MaxRegistrationRetryTime = 1800;              // RFC5626 section 4.5 default
00042 static unsigned int BaseRegistrationRetryTimeAllFlowsFailed = 30; // RFC5626 section 4.5 default
00043 //static unsigned int BaseRegistrationRetryTime = 90;               // RFC5626 section 4.5 default
00044 static unsigned int NotifySendTime = 30;  // If someone subscribes to our test event package, then send notifies every 30 seconds
00045 static unsigned int FailedSubscriptionRetryTime = 60; 
00046 
00047 //#define TEST_PASSING_A1_HASH_FOR_PASSWORD
00048 
00049 namespace resip
00050 {
00051 class ClientAppDialogSetFactory : public AppDialogSetFactory
00052 {
00053 public:
00054    ClientAppDialogSetFactory(BasicClientUserAgent& ua) : mUserAgent(ua) {}
00055    resip::AppDialogSet* createAppDialogSet(DialogUsageManager& dum, const SipMessage& msg)
00056    {
00057       switch(msg.method())
00058       {
00059          case INVITE:
00060             return new BasicClientCall(mUserAgent);
00061             break;
00062          default:         
00063             return AppDialogSetFactory::createAppDialogSet(dum, msg); 
00064             break;
00065       }
00066    }
00067 private:
00068    BasicClientUserAgent& mUserAgent;
00069 };
00070 
00071 // Used to set the IP Address in outbound SDP to match the IP address choosen by the stack to send the message on
00072 class SdpMessageDecorator : public MessageDecorator
00073 {
00074 public:
00075    virtual ~SdpMessageDecorator() {}
00076    virtual void decorateMessage(SipMessage &msg, 
00077                                 const Tuple &source,
00078                                 const Tuple &destination,
00079                                 const Data& sigcompId)
00080    {
00081       SdpContents* sdp = dynamic_cast<SdpContents*>(msg.getContents());
00082       if(sdp)  
00083       {
00084          // Fill in IP and Port from source
00085          sdp->session().connection().setAddress(Tuple::inet_ntop(source), source.ipVersion() == V6 ? SdpContents::IP6 : SdpContents::IP4);
00086          sdp->session().origin().setAddress(Tuple::inet_ntop(source), source.ipVersion() == V6 ? SdpContents::IP6 : SdpContents::IP4);
00087          InfoLog( << "SdpMessageDecorator: src=" << source << ", dest=" << destination << ", msg=" << endl << msg.brief());
00088       }
00089    }
00090    virtual void rollbackMessage(SipMessage& msg) {}  // Nothing to do
00091    virtual MessageDecorator* clone() const { return new SdpMessageDecorator; }
00092 };
00093 
00094 class NotifyTimer : public resip::DumCommand
00095 {
00096    public:
00097       NotifyTimer(BasicClientUserAgent& userAgent, unsigned int timerId) : mUserAgent(userAgent), mTimerId(timerId) {}
00098       NotifyTimer(const NotifyTimer& rhs) : mUserAgent(rhs.mUserAgent), mTimerId(rhs.mTimerId) {}
00099       ~NotifyTimer() {}
00100 
00101       void executeCommand() { mUserAgent.onNotifyTimeout(mTimerId); }
00102 
00103       resip::Message* clone() const { return new NotifyTimer(*this); }
00104       EncodeStream& encode(EncodeStream& strm) const { strm << "NotifyTimer: id=" << mTimerId; return strm; }
00105       EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); }
00106 
00107    private:
00108       BasicClientUserAgent& mUserAgent;
00109       unsigned int mTimerId;
00110 };
00111 } // end namespace
00112 
00113 BasicClientUserAgent::BasicClientUserAgent(int argc, char** argv) : 
00114    BasicClientCmdLineParser(argc, argv),
00115    mProfile(new MasterProfile),
00116 #if defined(USE_SSL)
00117    mSecurity(new Security(mCertPath)),
00118 #else
00119    mSecurity(0),
00120 #endif
00121    mStack(mSecurity, DnsStub::EmptyNameserverList, &mSelectInterruptor),
00122    mDum(new DialogUsageManager(mStack)),
00123    mStackThread(mStack, mSelectInterruptor),
00124    mDumShutdownRequested(false),
00125    mDumShutdown(false),
00126    mRegistrationRetryDelayTime(0),
00127    mCurrentNotifyTimerId(0)
00128 {
00129    Log::initialize(mLogType, mLogLevel, argv[0]);
00130 
00131    if(mHostFileLookupOnlyDnsMode)
00132    {
00133       AresDns::enableHostFileLookupOnlyMode(true);
00134    }
00135 
00136    addTransport(UDP, mUdpPort);
00137    addTransport(TCP, mTcpPort);
00138 #if defined(USE_SSL)
00139    addTransport(TLS, mTlsPort);
00140 #endif
00141 #if defined(USE_DTLS)
00142    addTransport(DTLS, mDtlsPort);
00143 #endif
00144 
00145    // Disable Statistics Manager
00146    mStack.statisticsManagerEnabled() = false;
00147 
00148    // Supported Methods
00149    mProfile->clearSupportedMethods();
00150    mProfile->addSupportedMethod(INVITE);
00151    mProfile->addSupportedMethod(ACK);
00152    mProfile->addSupportedMethod(CANCEL);
00153    mProfile->addSupportedMethod(OPTIONS);
00154    mProfile->addSupportedMethod(BYE);
00155    //mProfile->addSupportedMethod(REFER);    
00156    mProfile->addSupportedMethod(NOTIFY);    
00157    mProfile->addSupportedMethod(SUBSCRIBE); 
00158    //mProfile->addSupportedMethod(UPDATE);    
00159    mProfile->addSupportedMethod(INFO);    
00160    mProfile->addSupportedMethod(MESSAGE);    
00161    //mProfile->addSupportedMethod(PRACK);     
00162    //mProfile->addSupportedOptionTag(Token(Symbols::C100rel));  // Automatically added when using setUacReliableProvisionalMode
00163    mProfile->setUacReliableProvisionalMode(MasterProfile::Supported);
00164    //mProfile->setUasReliableProvisionalMode(MasterProfile::Supported);  // TODO - needs support in DUM, currently unimplemented
00165 
00166    // Support Languages
00167    mProfile->clearSupportedLanguages();
00168    mProfile->addSupportedLanguage(Token("en"));  
00169 
00170    // Support Mime Types
00171    mProfile->clearSupportedMimeTypes();
00172    mProfile->addSupportedMimeType(INVITE, Mime("application", "sdp"));
00173    mProfile->addSupportedMimeType(INVITE, Mime("multipart", "mixed"));  
00174    mProfile->addSupportedMimeType(INVITE, Mime("multipart", "signed"));  
00175    mProfile->addSupportedMimeType(INVITE, Mime("multipart", "alternative"));  
00176    mProfile->addSupportedMimeType(OPTIONS,Mime("application", "sdp"));
00177    mProfile->addSupportedMimeType(OPTIONS,Mime("multipart", "mixed"));  
00178    mProfile->addSupportedMimeType(OPTIONS, Mime("multipart", "signed"));  
00179    mProfile->addSupportedMimeType(OPTIONS, Mime("multipart", "alternative"));  
00180    mProfile->addSupportedMimeType(PRACK,  Mime("application", "sdp"));  
00181    mProfile->addSupportedMimeType(PRACK,  Mime("multipart", "mixed"));  
00182    mProfile->addSupportedMimeType(PRACK,  Mime("multipart", "signed"));  
00183    mProfile->addSupportedMimeType(PRACK,  Mime("multipart", "alternative"));  
00184    mProfile->addSupportedMimeType(UPDATE, Mime("application", "sdp"));  
00185    mProfile->addSupportedMimeType(UPDATE, Mime("multipart", "mixed"));  
00186    mProfile->addSupportedMimeType(UPDATE, Mime("multipart", "signed"));  
00187    mProfile->addSupportedMimeType(UPDATE, Mime("multipart", "alternative"));  
00188    mProfile->addSupportedMimeType(MESSAGE, Mime("text","plain")); // Invite session in-dialog routing testing
00189    mProfile->addSupportedMimeType(NOTIFY, Mime("text","plain"));  // subscription testing
00190    //mProfile->addSupportedMimeType(NOTIFY, Mime("message", "sipfrag"));  
00191 
00192    // Supported Options Tags
00193    mProfile->clearSupportedOptionTags();
00194    //mMasterProfile->addSupportedOptionTag(Token(Symbols::Replaces));      
00195    mProfile->addSupportedOptionTag(Token(Symbols::Timer));     // Enable Session Timers
00196    if(mOutboundEnabled)
00197    {
00198       mProfile->addSupportedOptionTag(Token(Symbols::Outbound));  // RFC 5626 - outbound
00199       mProfile->addSupportedOptionTag(Token(Symbols::Path));      // RFC 3327 - path
00200    }
00201    //mMasterProfile->addSupportedOptionTag(Token(Symbols::NoReferSub));
00202    //mMasterProfile->addSupportedOptionTag(Token(Symbols::TargetDialog));
00203 
00204    // Supported Schemes
00205    mProfile->clearSupportedSchemes();
00206    mProfile->addSupportedScheme("sip");  
00207 #if defined(USE_SSL)
00208    mProfile->addSupportedScheme("sips");  
00209 #endif
00210 
00211    // Validation Settings
00212    mProfile->validateContentEnabled() = false;
00213    mProfile->validateContentLanguageEnabled() = false;
00214    mProfile->validateAcceptEnabled() = false;
00215 
00216    // Have stack add Allow/Supported/Accept headers to INVITE dialog establishment messages
00217    mProfile->clearAdvertisedCapabilities(); // Remove Profile Defaults, then add our preferences
00218    mProfile->addAdvertisedCapability(Headers::Allow);  
00219    //mProfile->addAdvertisedCapability(Headers::AcceptEncoding);  // This can be misleading - it might specify what is expected in response
00220    mProfile->addAdvertisedCapability(Headers::AcceptLanguage);  
00221    mProfile->addAdvertisedCapability(Headers::Supported);  
00222    mProfile->setMethodsParamEnabled(true);
00223 
00224    // Install Sdp Message Decorator
00225    SharedPtr<MessageDecorator> outboundDecorator(new SdpMessageDecorator);
00226    mProfile->setOutboundDecorator(outboundDecorator);
00227 
00228    // Other Profile Settings
00229    mProfile->setUserAgent("basicClient/1.0");
00230    mProfile->setDefaultRegistrationTime(mRegisterDuration);
00231    mProfile->setDefaultRegistrationRetryTime(120);
00232    if(!mContact.host().empty())
00233    {
00234       mProfile->setOverrideHostAndPort(mContact);
00235    }
00236    if(!mOutboundProxy.host().empty())
00237    {
00238       mProfile->setOutboundProxy(Uri(mOutboundProxy));
00239       //mProfile->setForceOutboundProxyOnAllRequestsEnabled(true);
00240       mProfile->setExpressOutboundAsRouteSetEnabled(true);
00241    }
00242 
00243    // UserProfile Settings
00244    mProfile->setDefaultFrom(NameAddr(mAor));
00245 #ifdef TEST_PASSING_A1_HASH_FOR_PASSWORD
00246    MD5Stream a1;
00247    a1 << mAor.user()
00248       << Symbols::COLON
00249       << mAor.host()
00250       << Symbols::COLON
00251       << mPassword;
00252    mProfile->setDigestCredential(mAor.host(), mAor.user(), a1.getHex(), true);   
00253 #else
00254    mProfile->setDigestCredential(mAor.host(), mAor.user(), mPassword);   
00255 #endif
00256    // Generate InstanceId appropriate for testing only.  Should be UUID that persists 
00257    // across machine re-starts and is unique to this applicaiton instance.  The one used 
00258    // here is only as unique as the hostname of this machine.  If someone runs two 
00259    // instances of this application on the same host for the same Aor, then things will 
00260    // break.  See RFC5626 section 4.1
00261    Data hostname = DnsUtil::getLocalHostName();
00262    Data instanceHash = hostname.md5().uppercase();
00263    assert(instanceHash.size() == 32);
00264    Data instanceId(48, Data::Preallocate);
00265    instanceId += "<urn:uuid:";
00266    instanceId += instanceHash.substr(0, 8);
00267    instanceId += "-";
00268    instanceId += instanceHash.substr(8, 4);
00269    instanceId += "-";
00270    instanceId += instanceHash.substr(12, 4);
00271    instanceId += "-";
00272    instanceId += instanceHash.substr(16, 4);
00273    instanceId += "-";
00274    instanceId += instanceHash.substr(20, 12);
00275    instanceId += ">";
00276    mProfile->setInstanceId(instanceId);  
00277    if(mOutboundEnabled)
00278    {
00279       mProfile->setRegId(1);
00280       mProfile->clientOutboundEnabled() = true;
00281    }
00282 
00283    // Install Managers
00284    mDum->setClientAuthManager(std::auto_ptr<ClientAuthManager>(new ClientAuthManager));
00285    mDum->setKeepAliveManager(std::auto_ptr<KeepAliveManager>(new KeepAliveManager));
00286    mProfile->setKeepAliveTimeForDatagram(30);
00287    mProfile->setKeepAliveTimeForStream(120);
00288 
00289    // Install Handlers
00290    mDum->setInviteSessionHandler(this); 
00291    mDum->setDialogSetHandler(this);
00292    mDum->addOutOfDialogHandler(OPTIONS, this);
00293    //mDum->addOutOfDialogHandler(REFER, this);
00294    mDum->setRedirectHandler(this);
00295    mDum->setClientRegistrationHandler(this);   
00296    mDum->addClientSubscriptionHandler("basicClientTest", this);   // fabricated test event package
00297    mDum->addServerSubscriptionHandler("basicClientTest", this);
00298 
00299    // Set AppDialogSetFactory
00300    auto_ptr<AppDialogSetFactory> dsf(new ClientAppDialogSetFactory(*this));
00301    mDum->setAppDialogSetFactory(dsf);
00302 
00303    mDum->setMasterProfile(mProfile);
00304 
00305    mDum->registerForConnectionTermination(this);
00306 }
00307 
00308 BasicClientUserAgent::~BasicClientUserAgent()
00309 {
00310    mStackThread.shutdown();
00311    mStackThread.join();
00312 
00313    delete mDum;
00314 }
00315 
00316 void
00317 BasicClientUserAgent::startup()
00318 {
00319    mStackThread.run(); 
00320 
00321    if (mRegisterDuration)
00322    {
00323       InfoLog (<< "register for " << mAor);
00324       mDum->send(mDum->makeRegistration(NameAddr(mAor)));
00325    }
00326    else
00327    {
00328       // If not registering then form subscription and/or call here.  If registering then we will start these
00329       // after the registration is successful.
00330 
00331       // Check if we should try to form a test subscription
00332       if(!mSubscribeTarget.host().empty())
00333       {
00334          SharedPtr<SipMessage> sub = mDum->makeSubscription(NameAddr(mSubscribeTarget), mProfile, "basicClientTest");
00335          mDum->send(sub);
00336       }
00337 
00338       // Check if we should try to form a test call
00339       if(!mCallTarget.host().empty())
00340       {
00341          BasicClientCall* newCall = new BasicClientCall(*this);
00342          newCall->initiateCall(mCallTarget, mProfile);
00343       }
00344    }
00345 }
00346 
00347 void
00348 BasicClientUserAgent::shutdown()
00349 {
00350    assert(mDum);
00351    mDumShutdownRequested = true; // Set flag so that shutdown operations can be run in dum process thread
00352 }
00353 
00354 bool
00355 BasicClientUserAgent::process(int timeoutMs)
00356 {
00357    if(!mDumShutdown)
00358    {
00359       if(mDumShutdownRequested)
00360       {
00361          // unregister
00362          if(mRegHandle.isValid())
00363          {
00364             mRegHandle->end();
00365          }
00366 
00367          // end any subscriptions
00368          if(mServerSubscriptionHandle.isValid())
00369          {
00370             mServerSubscriptionHandle->end();
00371          }
00372          if(mClientSubscriptionHandle.isValid())
00373          {
00374             mClientSubscriptionHandle->end();
00375          }
00376 
00377          // End all calls - copy list in case delete/unregister of call is immediate
00378          std::set<BasicClientCall*> tempCallList = mCallList;
00379          std::set<BasicClientCall*>::iterator it = tempCallList.begin();
00380          for(; it != tempCallList.end(); it++)
00381          {
00382             (*it)->terminateCall();
00383          }
00384 
00385          mDum->shutdown(this);
00386          mDumShutdownRequested = false;
00387       }
00388       mDum->process(timeoutMs);
00389       return true;
00390    }
00391    return false;
00392 }
00393 
00394 void
00395 BasicClientUserAgent::addTransport(TransportType type, int port)
00396 {
00397    if(port == 0) return;  // Transport disabled
00398 
00399    for (int i=0; i < 10; ++i)
00400    {
00401       try
00402       {
00403          if (!mNoV4)
00404          {
00405             mStack.addTransport(type, port+i, V4, StunEnabled, Data::Empty, mTlsDomain);
00406             return;
00407          }
00408 
00409          if (mEnableV6)
00410          {
00411             mStack.addTransport(type, port+i, V6, StunEnabled, Data::Empty, mTlsDomain);
00412             return;
00413          }
00414       }
00415       catch (BaseException& e)
00416       {
00417          InfoLog (<< "Caught: " << e);
00418          WarningLog (<< "Failed to add " << Tuple::toData(type) << " transport on " << port);
00419       }
00420    }
00421    throw Transport::Exception("Port already in use", __FILE__, __LINE__);
00422 }
00423 
00424 void 
00425 BasicClientUserAgent::post(Message* msg)
00426 {
00427    ConnectionTerminated* terminated = dynamic_cast<ConnectionTerminated*>(msg);
00428    if (terminated)
00429    {
00430       InfoLog(<< "BasicClientUserAgent received connection terminated message for: " << terminated->getFlow());
00431       delete msg;
00432       return;
00433    }
00434    assert(false);
00435 }
00436 
00437 void 
00438 BasicClientUserAgent::onNotifyTimeout(unsigned int timerId)
00439 {
00440    if(timerId == mCurrentNotifyTimerId)
00441    {
00442       sendNotify();
00443    }
00444 }
00445 
00446 void
00447 BasicClientUserAgent::sendNotify()
00448 {
00449    if(mServerSubscriptionHandle.isValid())
00450    {
00451       PlainContents plain("test notify");
00452       mServerSubscriptionHandle->send(mServerSubscriptionHandle->update(&plain));
00453 
00454       // start timer for next one
00455       auto_ptr<ApplicationMessage> timer(new NotifyTimer(*this, ++mCurrentNotifyTimerId));
00456       mStack.post(timer, NotifySendTime, mDum);
00457    }
00458 }
00459 
00460 void 
00461 BasicClientUserAgent::onCallTimeout(BasicClientCall* call)
00462 {
00463    if(isValidCall(call))
00464    {
00465       call->timerExpired();
00466    }
00467    else  // call no longer exists
00468    {
00469       // If there are no more calls, then start a new one
00470       if(mCallList.empty() && !mCallTarget.host().empty())
00471       {
00472          // re-start a new call
00473          BasicClientCall* newCall = new BasicClientCall(*this);
00474          newCall->initiateCall(mCallTarget, mProfile);
00475       }
00476    }
00477 }
00478 
00479 void 
00480 BasicClientUserAgent::registerCall(BasicClientCall* call)
00481 {
00482    mCallList.insert(call);
00483 }
00484 
00485 void 
00486 BasicClientUserAgent::unregisterCall(BasicClientCall* call)
00487 {
00488    std::set<BasicClientCall*>::iterator it = mCallList.find(call);
00489    if(it != mCallList.end())
00490    {
00491       mCallList.erase(it);
00492    }
00493 }
00494 
00495 bool 
00496 BasicClientUserAgent::isValidCall(BasicClientCall* call)
00497 {
00498    std::set<BasicClientCall*>::iterator it = mCallList.find(call);
00499    if(it != mCallList.end())
00500    {
00501       return true;
00502    }
00503    return false;
00504 }
00505 
00506 void 
00507 BasicClientUserAgent::onDumCanBeDeleted()
00508 {
00509    mDumShutdown = true;
00510 }
00511 
00513 // Registration Handler ////////////////////////////////////////////////////////
00515 void 
00516 BasicClientUserAgent::onSuccess(ClientRegistrationHandle h, const SipMessage& msg)
00517 {
00518    InfoLog(<< "onSuccess(ClientRegistrationHandle): msg=" << msg.brief());
00519    if(mRegHandle.getId() == 0)  // Note: reg handle id will only be 0 on first successful registration
00520    {
00521       // Check if we should try to form a test subscription
00522       if(!mSubscribeTarget.host().empty())
00523       {
00524          SharedPtr<SipMessage> sub = mDum->makeSubscription(NameAddr(mSubscribeTarget), mProfile, "basicClientTest");
00525          mDum->send(sub);
00526       }
00527 
00528       // Check if we should try to form a test call
00529       if(!mCallTarget.host().empty())
00530       {
00531          BasicClientCall* newCall = new BasicClientCall(*this);
00532          newCall->initiateCall(mCallTarget, mProfile);
00533       }
00534    }
00535    mRegHandle = h;
00536    mRegistrationRetryDelayTime = 0;  // reset
00537 }
00538 
00539 void
00540 BasicClientUserAgent::onFailure(ClientRegistrationHandle h, const SipMessage& msg)
00541 {
00542    InfoLog(<< "onFailure(ClientRegistrationHandle): msg=" << msg.brief());
00543    mRegHandle = h;
00544 }
00545 
00546 void
00547 BasicClientUserAgent::onRemoved(ClientRegistrationHandle h, const SipMessage&msg)
00548 {
00549    InfoLog(<< "onRemoved(ClientRegistrationHandle): msg=" << msg.brief());
00550    mRegHandle = h;
00551 }
00552 
00553 int 
00554 BasicClientUserAgent::onRequestRetry(ClientRegistrationHandle h, int retryMinimum, const SipMessage& msg)
00555 {
00556    mRegHandle = h;
00557 
00558    if(mRegistrationRetryDelayTime == 0)
00559    {
00560       mRegistrationRetryDelayTime = BaseRegistrationRetryTimeAllFlowsFailed; // We only have one flow in this test app
00561    }
00562 
00563    // Use back off procedures of RFC 5626 section 4.5
00564    mRegistrationRetryDelayTime = resipMin(MaxRegistrationRetryTime, mRegistrationRetryDelayTime * 2);
00565 
00566    // return an evenly distributed random number between 50% and 100% of mRegistrationRetryDelayTime
00567    int retryTime = Helper::jitterValue(mRegistrationRetryDelayTime, 50, 100);
00568    InfoLog(<< "onRequestRetry(ClientRegistrationHandle): msg=" << msg.brief() << ", retryTime=" << retryTime);
00569 
00570    return retryTime;
00571 }
00572 
00573 
00575 // InviteSessionHandler ////////////////////////////////////////////////////////
00577 void
00578 BasicClientUserAgent::onNewSession(ClientInviteSessionHandle h, InviteSession::OfferAnswerType oat, const SipMessage& msg)
00579 {
00580    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onNewSession(h, oat, msg);
00581 }
00582 
00583 void
00584 BasicClientUserAgent::onNewSession(ServerInviteSessionHandle h, InviteSession::OfferAnswerType oat, const SipMessage& msg)
00585 {
00586    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onNewSession(h, oat, msg);
00587 }
00588 
00589 void
00590 BasicClientUserAgent::onFailure(ClientInviteSessionHandle h, const SipMessage& msg)
00591 {
00592    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onFailure(h, msg);
00593 }
00594 
00595 void
00596 BasicClientUserAgent::onEarlyMedia(ClientInviteSessionHandle h, const SipMessage& msg, const SdpContents& sdp)
00597 {
00598    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onEarlyMedia(h, msg, sdp);
00599 }
00600 
00601 void
00602 BasicClientUserAgent::onProvisional(ClientInviteSessionHandle h, const SipMessage& msg)
00603 {
00604    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onProvisional(h, msg);
00605 }
00606 
00607 void
00608 BasicClientUserAgent::onConnected(ClientInviteSessionHandle h, const SipMessage& msg)
00609 {
00610    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onConnected(h, msg);
00611 }
00612 
00613 void
00614 BasicClientUserAgent::onConnected(InviteSessionHandle h, const SipMessage& msg)
00615 {
00616    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onConnected(h, msg);
00617 }
00618 
00619 void
00620 BasicClientUserAgent::onStaleCallTimeout(ClientInviteSessionHandle h)
00621 {
00622    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onStaleCallTimeout(h);
00623 }
00624 
00625 void
00626 BasicClientUserAgent::onTerminated(InviteSessionHandle h, InviteSessionHandler::TerminatedReason reason, const SipMessage* msg)
00627 {
00628    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onTerminated(h, reason, msg);
00629 }
00630 
00631 void
00632 BasicClientUserAgent::onRedirected(ClientInviteSessionHandle h, const SipMessage& msg)
00633 {
00634    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onRedirected(h, msg);
00635 }
00636 
00637 void
00638 BasicClientUserAgent::onAnswer(InviteSessionHandle h, const SipMessage& msg, const SdpContents& sdp)
00639 {
00640    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onAnswer(h, msg, sdp);
00641 }
00642 
00643 void
00644 BasicClientUserAgent::onOffer(InviteSessionHandle h, const SipMessage& msg, const SdpContents& sdp)
00645 {         
00646    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onOffer(h, msg, sdp);
00647 }
00648 
00649 void
00650 BasicClientUserAgent::onOfferRequired(InviteSessionHandle h, const SipMessage& msg)
00651 {
00652    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onOfferRequired(h, msg);
00653 }
00654 
00655 void
00656 BasicClientUserAgent::onOfferRejected(InviteSessionHandle h, const SipMessage* msg)
00657 {
00658    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onOfferRejected(h, msg);
00659 }
00660 
00661 void
00662 BasicClientUserAgent::onOfferRequestRejected(InviteSessionHandle h, const SipMessage& msg)
00663 {
00664    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onOfferRequestRejected(h, msg);
00665 }
00666 
00667 void
00668 BasicClientUserAgent::onRemoteSdpChanged(InviteSessionHandle h, const SipMessage& msg, const SdpContents& sdp)
00669 {
00670    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onRemoteSdpChanged(h, msg, sdp);
00671 }
00672 
00673 void
00674 BasicClientUserAgent::onInfo(InviteSessionHandle h, const SipMessage& msg)
00675 {
00676    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onInfo(h, msg);
00677 }
00678 
00679 void
00680 BasicClientUserAgent::onInfoSuccess(InviteSessionHandle h, const SipMessage& msg)
00681 {
00682    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onInfoSuccess(h, msg);
00683 }
00684 
00685 void
00686 BasicClientUserAgent::onInfoFailure(InviteSessionHandle h, const SipMessage& msg)
00687 {
00688    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onInfoFailure(h, msg);
00689 }
00690 
00691 void
00692 BasicClientUserAgent::onRefer(InviteSessionHandle h, ServerSubscriptionHandle ssh, const SipMessage& msg)
00693 {
00694    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onRefer(h, ssh, msg);
00695 }
00696 
00697 void
00698 BasicClientUserAgent::onReferAccepted(InviteSessionHandle h, ClientSubscriptionHandle csh, const SipMessage& msg)
00699 {
00700    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onReferAccepted(h, csh, msg);
00701 }
00702 
00703 void
00704 BasicClientUserAgent::onReferRejected(InviteSessionHandle h, const SipMessage& msg)
00705 {
00706    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onReferRejected(h, msg);
00707 }
00708 
00709 void
00710 BasicClientUserAgent::onReferNoSub(InviteSessionHandle h, const SipMessage& msg)
00711 {
00712    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onReferNoSub(h, msg);
00713 }
00714 
00715 void
00716 BasicClientUserAgent::onMessage(InviteSessionHandle h, const SipMessage& msg)
00717 {
00718    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onMessage(h, msg);
00719 }
00720 
00721 void
00722 BasicClientUserAgent::onMessageSuccess(InviteSessionHandle h, const SipMessage& msg)
00723 {
00724    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onMessageSuccess(h, msg);
00725 }
00726 
00727 void
00728 BasicClientUserAgent::onMessageFailure(InviteSessionHandle h, const SipMessage& msg)
00729 {
00730    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onMessageFailure(h, msg);
00731 }
00732 
00733 void
00734 BasicClientUserAgent::onForkDestroyed(ClientInviteSessionHandle h)
00735 {
00736    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onForkDestroyed(h);
00737 }
00738 
00739 void 
00740 BasicClientUserAgent::onReadyToSend(InviteSessionHandle h, SipMessage& msg)
00741 {
00742    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onReadyToSend(h, msg);
00743 }
00744 
00745 void 
00746 BasicClientUserAgent::onFlowTerminated(InviteSessionHandle h)
00747 {
00748    dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get())->onFlowTerminated(h);
00749 }
00750 
00751 
00753 // DialogSetHandler ///////////////////////////////////////////////////
00755 void 
00756 BasicClientUserAgent::onTrying(AppDialogSetHandle h, const SipMessage& msg)
00757 {
00758    BasicClientCall *call = dynamic_cast<BasicClientCall *>(h.get());
00759    if(call)
00760    {
00761       call->onTrying(h, msg);
00762    }
00763    else
00764    {
00765       InfoLog(<< "onTrying(AppDialogSetHandle): " << msg.brief());
00766    }
00767 }
00768 
00769 void 
00770 BasicClientUserAgent::onNonDialogCreatingProvisional(AppDialogSetHandle h, const SipMessage& msg)
00771 {
00772    BasicClientCall *call = dynamic_cast<BasicClientCall *>(h.get());
00773    if(call)
00774    {
00775       call->onNonDialogCreatingProvisional(h, msg);
00776    }
00777    else
00778    {
00779       InfoLog(<< "onNonDialogCreatingProvisional(AppDialogSetHandle): " << msg.brief());
00780    }
00781 }
00782 
00784 // ClientSubscriptionHandler ///////////////////////////////////////////////////
00786 void
00787 BasicClientUserAgent::onUpdatePending(ClientSubscriptionHandle h, const SipMessage& msg, bool outOfOrder)
00788 {
00789    BasicClientCall* call = dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get());
00790    if(call)
00791    {
00792       call->onUpdatePending(h, msg, outOfOrder);
00793       return;
00794    }
00795    InfoLog(<< "onUpdatePending(ClientSubscriptionHandle): " << msg.brief());
00796    h->acceptUpdate();
00797 }
00798 
00799 void
00800 BasicClientUserAgent::onUpdateActive(ClientSubscriptionHandle h, const SipMessage& msg, bool outOfOrder)
00801 {
00802    BasicClientCall* call = dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get());
00803    if(call)
00804    {
00805       call->onUpdateActive(h, msg, outOfOrder);
00806       return;
00807    }
00808    InfoLog(<< "onUpdateActive(ClientSubscriptionHandle): " << msg.brief());
00809    h->acceptUpdate();
00810 }
00811 
00812 void
00813 BasicClientUserAgent::onUpdateExtension(ClientSubscriptionHandle h, const SipMessage& msg, bool outOfOrder)
00814 {
00815    BasicClientCall* call = dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get());
00816    if(call)
00817    {
00818       call->onUpdateExtension(h, msg, outOfOrder);
00819       return;
00820    }
00821    InfoLog(<< "onUpdateExtension(ClientSubscriptionHandle): " << msg.brief());
00822    h->acceptUpdate();
00823 }
00824 
00825 void 
00826 BasicClientUserAgent::onNotifyNotReceived(ClientSubscriptionHandle h)
00827 {
00828    BasicClientCall* call = dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get());
00829    if(call)
00830    {
00831       call->onNotifyNotReceived(h);
00832       return;
00833    }
00834    WarningLog(<< "onNotifyNotReceived(ClientSubscriptionHandle)");
00835    h->end();
00836 }
00837 
00838 void
00839 BasicClientUserAgent::onTerminated(ClientSubscriptionHandle h, const SipMessage* msg)
00840 {
00841    BasicClientCall* call = dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get());
00842    if(call)
00843    {
00844       call->onTerminated(h, msg);
00845       return;
00846    }
00847    if(msg)
00848    {
00849       InfoLog(<< "onTerminated(ClientSubscriptionHandle): msg=" << msg->brief());
00850    }
00851    else
00852    {
00853       InfoLog(<< "onTerminated(ClientSubscriptionHandle)");
00854    }
00855 }
00856 
00857 void
00858 BasicClientUserAgent::onNewSubscription(ClientSubscriptionHandle h, const SipMessage& msg)
00859 {
00860    BasicClientCall* call = dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get());
00861    if(call)
00862    {
00863       call->onNewSubscription(h, msg);
00864       return;
00865    }
00866    mClientSubscriptionHandle = h;
00867    InfoLog(<< "onNewSubscription(ClientSubscriptionHandle): msg=" << msg.brief());
00868 }
00869 
00870 int 
00871 BasicClientUserAgent::onRequestRetry(ClientSubscriptionHandle h, int retrySeconds, const SipMessage& msg)
00872 {
00873    BasicClientCall* call = dynamic_cast<BasicClientCall *>(h->getAppDialogSet().get());
00874    if(call)
00875    {
00876       return call->onRequestRetry(h, retrySeconds, msg);
00877    }
00878    InfoLog(<< "onRequestRetry(ClientSubscriptionHandle): msg=" << msg.brief());
00879    return FailedSubscriptionRetryTime;  
00880 }
00881 
00883 // ServerSubscriptionHandler ///////////////////////////////////////////////////
00885 void 
00886 BasicClientUserAgent::onNewSubscription(ServerSubscriptionHandle h, const SipMessage& msg)
00887 {
00888    InfoLog(<< "onNewSubscription(ServerSubscriptionHandle): " << msg.brief());
00889 
00890    mServerSubscriptionHandle = h;
00891    mServerSubscriptionHandle->setSubscriptionState(Active);
00892    mServerSubscriptionHandle->send(mServerSubscriptionHandle->accept());
00893 
00894    sendNotify();
00895 }
00896 
00897 void 
00898 BasicClientUserAgent::onNewSubscriptionFromRefer(ServerSubscriptionHandle ss, const SipMessage& msg)
00899 {
00900    InfoLog(<< "onNewSubscriptionFromRefer(ServerSubscriptionHandle): " << msg.brief());
00901    // Received an out-of-dialog refer request with implicit subscription
00902    try
00903    {
00904       if(msg.exists(h_ReferTo))
00905       {
00906          // Check if TargetDialog header is present
00907          if(msg.exists(h_TargetDialog))
00908          {
00909             pair<InviteSessionHandle, int> presult;
00910             presult = mDum->findInviteSession(msg.header(h_TargetDialog));
00911             if(!(presult.first == InviteSessionHandle::NotValid())) 
00912             {         
00913                BasicClientCall* callToRefer = (BasicClientCall*)presult.first->getAppDialogSet().get();
00914 
00915                callToRefer->onRefer(presult.first, ss, msg);
00916                return;
00917             }
00918          }
00919 
00920          // We don't support ood refers that don't target a dialog - reject request 
00921          WarningLog (<< "onNewSubscriptionFromRefer(ServerSubscriptionHandle): Received ood refer (noSub) w/out a Target-Dialog: " << msg.brief());
00922          ss->send(ss->reject(400));
00923       }
00924       else
00925       {
00926          WarningLog (<< "onNewSubscriptionFromRefer(ServerSubscriptionHandle): Received refer w/out a Refer-To: " << msg.brief());
00927          ss->send(ss->reject(400));
00928       }
00929    }
00930    catch(BaseException &e)
00931    {
00932       WarningLog(<< "onNewSubscriptionFromRefer(ServerSubscriptionHandle): exception " << e);
00933    }
00934    catch(...)
00935    {
00936       WarningLog(<< "onNewSubscriptionFromRefer(ServerSubscriptionHandle): unknown exception");
00937    }
00938 }
00939 
00940 void 
00941 BasicClientUserAgent::onRefresh(ServerSubscriptionHandle, const SipMessage& msg)
00942 {
00943    InfoLog(<< "onRefresh(ServerSubscriptionHandle): " << msg.brief());
00944 }
00945 
00946 void 
00947 BasicClientUserAgent::onTerminated(ServerSubscriptionHandle)
00948 {
00949    InfoLog(<< "onTerminated(ServerSubscriptionHandle)");
00950 }
00951 
00952 void 
00953 BasicClientUserAgent::onReadyToSend(ServerSubscriptionHandle, SipMessage&)
00954 {
00955 }
00956 
00957 void 
00958 BasicClientUserAgent::onNotifyRejected(ServerSubscriptionHandle, const SipMessage& msg)
00959 {
00960    WarningLog(<< "onNotifyRejected(ServerSubscriptionHandle): " << msg.brief());
00961 }
00962 
00963 void 
00964 BasicClientUserAgent::onError(ServerSubscriptionHandle, const SipMessage& msg)
00965 {
00966    WarningLog(<< "onError(ServerSubscriptionHandle): " << msg.brief());
00967 }
00968 
00969 void 
00970 BasicClientUserAgent::onExpiredByClient(ServerSubscriptionHandle, const SipMessage& sub, SipMessage& notify)
00971 {
00972    InfoLog(<< "onExpiredByClient(ServerSubscriptionHandle): " << notify.brief());
00973 }
00974 
00975 void 
00976 BasicClientUserAgent::onExpired(ServerSubscriptionHandle, SipMessage& msg)
00977 {
00978    InfoLog(<< "onExpired(ServerSubscriptionHandle): " << msg.brief());
00979 }
00980 
00981 bool 
00982 BasicClientUserAgent::hasDefaultExpires() const
00983 {
00984    return true;
00985 }
00986 
00987 UInt32 
00988 BasicClientUserAgent::getDefaultExpires() const
00989 {
00990    return 60;
00991 }
00992 
00994 // OutOfDialogHandler //////////////////////////////////////////////////////////
00996 void 
00997 BasicClientUserAgent::onSuccess(ClientOutOfDialogReqHandle, const SipMessage& msg)
00998 {
00999    InfoLog(<< "onSuccess(ClientOutOfDialogReqHandle): " << msg.brief());
01000 }
01001 
01002 void 
01003 BasicClientUserAgent::onFailure(ClientOutOfDialogReqHandle h, const SipMessage& msg)
01004 {
01005    WarningLog(<< "onFailure(ClientOutOfDialogReqHandle): " << msg.brief());
01006 }
01007 
01008 void 
01009 BasicClientUserAgent::onReceivedRequest(ServerOutOfDialogReqHandle ood, const SipMessage& msg)
01010 {
01011    InfoLog(<< "onReceivedRequest(ServerOutOfDialogReqHandle): " << msg.brief());
01012 
01013    switch(msg.method())
01014    {
01015    case OPTIONS:
01016       {
01017          SharedPtr<SipMessage> optionsAnswer = ood->answerOptions();
01018          ood->send(optionsAnswer);
01019          break;
01020       }
01021    default:
01022       ood->send(ood->reject(501 /* Not Implemented*/));
01023       break;
01024    }
01025 }
01026 
01028 // RedirectHandler /////////////////////////////////////////////////////////////
01030 void 
01031 BasicClientUserAgent::onRedirectReceived(AppDialogSetHandle h, const SipMessage& msg)
01032 {
01033    BasicClientCall* call = dynamic_cast<BasicClientCall *>(h.get());
01034    if(call)
01035    {
01036       call->onRedirectReceived(h, msg);
01037    }
01038    else
01039    {
01040       InfoLog(<< "onRedirectReceived(AppDialogSetHandle): " << msg.brief());
01041    }
01042 }
01043 
01044 bool 
01045 BasicClientUserAgent::onTryingNextTarget(AppDialogSetHandle, const SipMessage& msg)
01046 {
01047    InfoLog(<< "onTryingNextTarget(AppDialogSetHandle): " << msg.brief());
01048 
01049    // Always allow redirection for now
01050    return true;
01051 }
01052 
01053 
01054 
01055 
01056 /* ====================================================================
01057 
01058  Copyright (c) 2011, SIP Spectrum, Inc.
01059  All rights reserved.
01060 
01061  Redistribution and use in source and binary forms, with or without
01062  modification, are permitted provided that the following conditions are 
01063  met:
01064 
01065  1. Redistributions of source code must retain the above copyright 
01066     notice, this list of conditions and the following disclaimer. 
01067 
01068  2. Redistributions in binary form must reproduce the above copyright
01069     notice, this list of conditions and the following disclaimer in the
01070     documentation and/or other materials provided with the distribution. 
01071 
01072  3. Neither the name of SIP Spectrum nor the names of its contributors 
01073     may be used to endorse or promote products derived from this 
01074     software without specific prior written permission. 
01075 
01076  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
01077  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
01078  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
01079  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
01080  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
01081  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
01082  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
01083  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
01084  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
01085  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
01086  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
01087 
01088  ==================================================================== */
01089