reSIProcate/DialogUsageManager  9694
basicClientCall.cxx
Go to the documentation of this file.
00001 #include "basicClientCall.hxx"
00002 
00003 #include <resip/stack/SdpContents.hxx>
00004 #include <resip/stack/PlainContents.hxx>
00005 #include <resip/stack/SipMessage.hxx>
00006 #include <resip/stack/ShutdownMessage.hxx>
00007 #include <resip/stack/SipStack.hxx>
00008 #include <resip/dum/ClientAuthManager.hxx>
00009 #include <resip/dum/ClientInviteSession.hxx>
00010 #include <resip/dum/ClientSubscription.hxx>
00011 #include <resip/dum/DialogUsageManager.hxx>
00012 #include <resip/dum/InviteSessionHandler.hxx>
00013 #include <resip/dum/MasterProfile.hxx>
00014 #include <resip/dum/ServerInviteSession.hxx>
00015 #include <resip/dum/AppDialog.hxx>
00016 #include <resip/dum/AppDialogSet.hxx>
00017 #include <resip/dum/AppDialogSetFactory.hxx>
00018 #include <rutil/Log.hxx>
00019 #include <rutil/Logger.hxx>
00020 #include <rutil/Random.hxx>
00021 #include <rutil/WinLeakCheck.hxx>
00022 
00023 #include <sstream>
00024 #include <time.h>
00025 
00026 #define RESIPROCATE_SUBSYSTEM Subsystem::TEST
00027 
00028 using namespace resip;
00029 using namespace std;
00030 
00031 static unsigned int CallTimerTime = 30;  // Time between call timer
00032 static unsigned int CallTimeCounterToByeOn = 6;  // BYE the call after the call timer has expired 6 times
00033 
00034 namespace resip
00035 {
00036 class CallTimer : public resip::DumCommand
00037 {
00038    public:
00039       CallTimer(BasicClientUserAgent& userAgent, BasicClientCall* call) : mUserAgent(userAgent), mCall(call) {}
00040       CallTimer(const CallTimer& rhs) : mUserAgent(rhs.mUserAgent), mCall(rhs.mCall) {}
00041       ~CallTimer() {}
00042 
00043       void executeCommand() { mUserAgent.onCallTimeout(mCall); }
00044 
00045       resip::Message* clone() const { return new CallTimer(*this); }
00046       EncodeStream& encode(EncodeStream& strm) const { strm << "CallTimer:"; return strm; }
00047       EncodeStream& encodeBrief(EncodeStream& strm) const { return encode(strm); }
00048 
00049    private:
00050       BasicClientUserAgent& mUserAgent;
00051       BasicClientCall* mCall;
00052 };
00053 }
00054 
00055 BasicClientCall::BasicClientCall(BasicClientUserAgent& userAgent) 
00056 : AppDialogSet(userAgent.getDialogUsageManager()),
00057   mUserAgent(userAgent),
00058   mTimerExpiredCounter(0),
00059   mPlacedCall(false),
00060   mUACConnectedDialogId(Data::Empty, Data::Empty, Data::Empty)
00061 {
00062    mUserAgent.registerCall(this);
00063 }
00064 
00065 BasicClientCall::~BasicClientCall()
00066 {
00067    mUserAgent.unregisterCall(this);
00068 }
00069 
00070 void 
00071 BasicClientCall::initiateCall(const Uri& target, SharedPtr<UserProfile> profile)
00072 {
00073    SdpContents offer;
00074    makeOffer(offer);
00075    SharedPtr<SipMessage> invite = mUserAgent.getDialogUsageManager().makeInviteSession(NameAddr(target), profile, &offer, this);
00076    mUserAgent.getDialogUsageManager().send(invite);
00077    mPlacedCall = true;
00078 }
00079 
00080 void 
00081 BasicClientCall::terminateCall()
00082 {
00083    AppDialogSet::end(); 
00084 }
00085 
00086 void 
00087 BasicClientCall::timerExpired()
00088 {
00089    mTimerExpiredCounter++;
00090    if(mTimerExpiredCounter < CallTimeCounterToByeOn)
00091    {
00092       // First few times, send a message to the other party
00093       if(mInviteSessionHandle.isValid())
00094       {
00095          PlainContents plain("test message");
00096          mInviteSessionHandle->message(plain);
00097       }
00098    }
00099    else 
00100    {
00101       // Then hangup
00102       terminateCall();
00103    }
00104 
00105    // start timer for next one
00106    auto_ptr<ApplicationMessage> timer(new CallTimer(mUserAgent, this));
00107    mUserAgent.mStack.post(timer, CallTimerTime, &mUserAgent.getDialogUsageManager());
00108 }
00109 
00110 SharedPtr<UserProfile> 
00111 BasicClientCall::selectUASUserProfile(const SipMessage& msg)
00112 {
00113    return mUserAgent.getIncomingUserProfile(msg);
00114 }
00115 
00116 bool 
00117 BasicClientCall::isUACConnected()
00118 {
00119    return !mUACConnectedDialogId.getCallId().empty();
00120 }
00121 
00122 bool 
00123 BasicClientCall::isStaleFork(const DialogId& dialogId)
00124 {
00125    return (!mUACConnectedDialogId.getCallId().empty() && dialogId != mUACConnectedDialogId);
00126 }
00127 
00128 void 
00129 BasicClientCall::makeOffer(SdpContents& offer)
00130 {
00131    static Data txt("v=0\r\n"
00132                    "o=- 0 0 IN IP4 0.0.0.0\r\n"
00133                    "s=basicClient\r\n"
00134                    "c=IN IP4 0.0.0.0\r\n"  
00135                    "t=0 0\r\n"
00136                    "m=audio 8000 RTP/AVP 0 101\r\n"
00137                    "a=rtpmap:0 pcmu/8000\r\n"
00138                    "a=rtpmap:101 telephone-event/8000\r\n"
00139                    "a=fmtp:101 0-15\r\n");
00140 
00141    static HeaderFieldValue hfv(txt.data(), txt.size());
00142    static Mime type("application", "sdp");
00143    static SdpContents offerSdp(hfv, type);
00144 
00145    offer = offerSdp;
00146 
00147    // Set sessionid and version for this offer
00148    UInt64 currentTime = Timer::getTimeMicroSec();
00149    offer.session().origin().getSessionId() = currentTime;
00150    offer.session().origin().getVersion() = currentTime;  
00151 }
00152 
00154 // InviteSessionHandler      ///////////////////////////////////////////////////
00156 
00157 void
00158 BasicClientCall::onNewSession(ClientInviteSessionHandle h, InviteSession::OfferAnswerType oat, const SipMessage& msg)
00159 {
00160    InfoLog(<< "onNewSession(ClientInviteSessionHandle): msg=" << msg.brief());
00161    mInviteSessionHandle = h->getSessionHandle();  // Note:  each forked leg will update mInviteSession - need to set mInviteSessionHandle for final answering leg on 200
00162    if(mInviteSessionHandleReplaced.isValid())
00163    {
00164        // See comment in flowTerminated for an explanation of this logic
00165        ((BasicClientCall*)mInviteSessionHandleReplaced->getAppDialogSet().get())->terminateCall();
00166    }
00167 }
00168 
00169 void
00170 BasicClientCall::onNewSession(ServerInviteSessionHandle h, InviteSession::OfferAnswerType oat, const SipMessage& msg)
00171 {
00172    InfoLog(<< "onNewSession(ServerInviteSessionHandle):  msg=" << msg.brief());
00173    mInviteSessionHandle = h->getSessionHandle();
00174 
00175    // First check if this INVITE is to replace an existing session
00176    if(msg.exists(h_Replaces))
00177    {
00178       pair<InviteSessionHandle, int> presult;
00179       presult = mDum.findInviteSession(msg.header(h_Replaces));
00180       if(!(presult.first == InviteSessionHandle::NotValid())) 
00181       {         
00182          BasicClientCall* callToReplace = dynamic_cast<BasicClientCall *>(presult.first->getAppDialogSet().get());
00183          InfoLog(<< "onNewSession(ServerInviteSessionHandle): replacing existing call");
00184 
00185          // Copy over flag that indicates if we placed the call or not
00186          mPlacedCall = callToReplace->mPlacedCall;
00187 
00188          if(mPlacedCall)
00189          {
00190             // Restart Call Timer
00191             auto_ptr<ApplicationMessage> timer(new CallTimer(mUserAgent, this));
00192             mUserAgent.mStack.post(timer, CallTimerTime, &mUserAgent.getDialogUsageManager());
00193          }
00194 
00195          // Session to replace was found - end old session
00196          callToReplace->end();
00197       }
00198       else
00199       {
00200           // Session to replace not found - reject it
00201           h->reject(481 /* Call/Transaction Does Not Exist */);
00202       }
00203    }
00204 }
00205 
00206 void
00207 BasicClientCall::onFailure(ClientInviteSessionHandle h, const SipMessage& msg)
00208 {
00209    WarningLog(<< "onFailure: msg=" << msg.brief());
00210 
00211    if (msg.isResponse()) 
00212    {
00213       switch(msg.header(h_StatusLine).statusCode()) 
00214       {
00215          case 408:
00216          case 503:
00217             if(msg.getReceivedTransport() == 0)
00218             {
00219                // Try another flow? 
00220             }
00221          default:
00222             break;
00223       }
00224    }
00225 }
00226 
00227 void
00228 BasicClientCall::onEarlyMedia(ClientInviteSessionHandle h, const SipMessage& msg, const SdpContents& sdp)
00229 {
00230    InfoLog(<< "onEarlyMedia: msg=" << msg.brief() << ", sdp=" << sdp);
00231 }
00232 
00233 void
00234 BasicClientCall::onProvisional(ClientInviteSessionHandle h, const SipMessage& msg)
00235 {
00236    InfoLog(<< "onProvisional: msg=" << msg.brief());
00237 
00238    if(isStaleFork(h->getDialogId()))
00239    {
00240       // If we receive a response from a stale fork (ie. after someone sends a 200), then we want to ignore it
00241       InfoLog(<< "onProvisional: from stale fork, msg=" << msg.brief());
00242       return;
00243    }
00244    InfoLog(<< "onProvisional: msg=" << msg.brief());
00245 }
00246 
00247 void
00248 BasicClientCall::onConnected(ClientInviteSessionHandle h, const SipMessage& msg)
00249 {
00250    InfoLog(<< "onConnected: msg=" << msg.brief());
00251    if(!isUACConnected())
00252    {
00253       // It is possible in forking scenarios to get multiple 200 responses, if this is 
00254       // our first 200 response, then this is the leg we accept, store the connected DialogId
00255       mUACConnectedDialogId = h->getDialogId();
00256       // Note:  each forked leg will update mInviteSessionHandle (in onNewSession call) - need to set mInviteSessionHandle for final answering leg on 200
00257       mInviteSessionHandle = h->getSessionHandle();  
00258 
00259       // start call timer
00260       auto_ptr<ApplicationMessage> timer(new CallTimer(mUserAgent, this));
00261       mUserAgent.mStack.post(timer, CallTimerTime, &mUserAgent.getDialogUsageManager());
00262    }
00263    else
00264    {
00265       // We already have a connected leg - end this one with a BYE
00266       h->end();
00267    }
00268 }
00269 
00270 void
00271 BasicClientCall::onConnected(InviteSessionHandle h, const SipMessage& msg)
00272 {
00273    InfoLog(<< "onConnected: msg=" << msg.brief());
00274 }
00275 
00276 void
00277 BasicClientCall::onStaleCallTimeout(ClientInviteSessionHandle h)
00278 {
00279    WarningLog(<< "onStaleCallTimeout");
00280 }
00281 
00282 void
00283 BasicClientCall::onTerminated(InviteSessionHandle h, InviteSessionHandler::TerminatedReason reason, const SipMessage* msg)
00284 {
00285    Data reasonData;
00286 
00287    switch(reason)
00288    {
00289    case InviteSessionHandler::RemoteBye:
00290       reasonData = "received a BYE from peer";
00291       break;
00292    case InviteSessionHandler::RemoteCancel:
00293       reasonData = "received a CANCEL from peer";
00294       break;   
00295    case InviteSessionHandler::Rejected:
00296       reasonData = "received a rejection from peer";
00297       break;
00298    case InviteSessionHandler::LocalBye:
00299       reasonData = "ended locally via BYE";
00300       break;
00301    case InviteSessionHandler::LocalCancel:
00302       reasonData = "ended locally via CANCEL";
00303       break;
00304    case InviteSessionHandler::Replaced:
00305       reasonData = "ended due to being replaced";
00306       break;
00307    case InviteSessionHandler::Referred:
00308       reasonData = "ended due to being referred";
00309       break;
00310    case InviteSessionHandler::Error:
00311       reasonData = "ended due to an error";
00312       break;
00313    case InviteSessionHandler::Timeout:
00314       reasonData = "ended due to a timeout";
00315       break;
00316    default:
00317       assert(false);
00318       break;
00319    }
00320 
00321    if(isStaleFork(h->getDialogId()))
00322    {
00323       // If we receive a response from a stale fork (ie. after someone sends a 200), then we want to ignore it
00324       if(msg)
00325       {
00326          InfoLog(<< "onTerminated: from stale fork, reason=" << reasonData << ", msg=" << msg->brief());
00327       }
00328       else
00329       {
00330          InfoLog(<< "onTerminated: from stale fork, reason=" << reasonData);
00331       }
00332       return;
00333    }
00334 
00335    if(msg)
00336    {
00337       InfoLog(<< "onTerminated: reason=" << reasonData << ", msg=" << msg->brief());
00338    }
00339    else
00340    {
00341       InfoLog(<< "onTerminated: reason=" << reasonData);
00342    }
00343 }
00344 
00345 void
00346 BasicClientCall::onRedirected(ClientInviteSessionHandle h, const SipMessage& msg)
00347 {
00348    // DUM will recurse on redirect requests, so nothing to do here
00349    InfoLog(<< "onRedirected: msg=" << msg.brief());
00350 }
00351 
00352 void
00353 BasicClientCall::onAnswer(InviteSessionHandle h, const SipMessage& msg, const SdpContents& sdp)
00354 {
00355    if(isStaleFork(h->getDialogId()))
00356    {
00357       // If we receive a response from a stale fork (ie. after someone sends a 200), then we want to ignore it
00358       InfoLog(<< "onAnswer: from stale fork, msg=" << msg.brief() << ", sdp=" << sdp);
00359       return;
00360    }
00361    InfoLog(<< "onAnswer: msg=" << msg.brief() << ", sdp=" << sdp);
00362 
00363    // Process Answer here
00364 }
00365 
00366 void
00367 BasicClientCall::onOffer(InviteSessionHandle h, const SipMessage& msg, const SdpContents& sdp)
00368 {         
00369    if(isStaleFork(h->getDialogId()))
00370    {
00371       // If we receive a response from a stale fork (ie. after someone sends a 200), then we want to ignore it
00372       InfoLog(<< "onOffer: from stale fork, msg=" << msg.brief() << ", sdp=" << sdp);
00373       return;
00374    }
00375    InfoLog(<< "onOffer: msg=" << msg.brief() << ", sdp=" << sdp);
00376 
00377    // Provide Answer here - for test client just echo back same SDP as received for now
00378    h->provideAnswer(sdp);
00379    ServerInviteSession* uas = dynamic_cast<ServerInviteSession*>(h.get());
00380    if(uas && !uas->isAccepted())
00381    {
00382       uas->accept();
00383    }
00384 }
00385 
00386 void
00387 BasicClientCall::onOfferRequired(InviteSessionHandle h, const SipMessage& msg)
00388 {
00389    if(isStaleFork(h->getDialogId()))
00390    {
00391       // If we receive a response from a stale fork (ie. after someone sends a 200), then we want to ignore it
00392       InfoLog(<< "onOfferRequired: from stale fork, msg=" << msg.brief());
00393       return;
00394    }
00395    InfoLog(<< "onOfferRequired: msg=" << msg.brief());
00396 
00397    // Provide Offer Here
00398    SdpContents offer;
00399    makeOffer(offer);
00400 
00401    h->provideOffer(offer);
00402 }
00403 
00404 void
00405 BasicClientCall::onOfferRejected(InviteSessionHandle h, const SipMessage* msg)
00406 {
00407    if(isStaleFork(h->getDialogId()))
00408    {
00409       // If we receive a response from a stale fork (ie. after someone sends a 200), then we want to ignore it
00410       if(msg)
00411       {
00412          WarningLog(<< "onOfferRejected: from stale fork, msg=" << msg->brief());
00413       }
00414       else
00415       {
00416          WarningLog(<< "onOfferRejected: from stale fork");
00417       }
00418       return;
00419    }
00420    if(msg)
00421    {
00422       WarningLog(<< "onOfferRejected: msg=" << msg->brief());
00423    }
00424    else
00425    {
00426       WarningLog(<< "onOfferRejected");
00427    }
00428 }
00429 
00430 void
00431 BasicClientCall::onOfferRequestRejected(InviteSessionHandle h, const SipMessage& msg)
00432 {
00433    InfoLog(<< "onOfferRequestRejected: msg=" << msg.brief());
00434    // This is called when we are waiting to resend a INVITE with no sdp after a glare condition, and we 
00435    // instead receive an inbound INVITE or UPDATE
00436 }
00437 
00438 void
00439 BasicClientCall::onRemoteSdpChanged(InviteSessionHandle h, const SipMessage& msg, const SdpContents& sdp)
00440 {
00446    InfoLog(<< "onRemoteSdpChanged: msg=" << msg << ", sdp=" << sdp);
00447 
00448    // Process SDP Answer here
00449 }
00450 
00451 void
00452 BasicClientCall::onInfo(InviteSessionHandle h, const SipMessage& msg)
00453 {
00454    InfoLog(<< "onInfo: msg=" << msg.brief());
00455 
00456    // Handle message here
00457    h->acceptNIT();
00458 }
00459 
00460 void
00461 BasicClientCall::onInfoSuccess(InviteSessionHandle h, const SipMessage& msg)
00462 {
00463    InfoLog(<< "onInfoSuccess: msg=" << msg.brief());
00464 }
00465 
00466 void
00467 BasicClientCall::onInfoFailure(InviteSessionHandle h, const SipMessage& msg)
00468 {
00469    WarningLog(<< "onInfoFailure: msg=" << msg.brief());
00470 }
00471 
00472 void
00473 BasicClientCall::onRefer(InviteSessionHandle h, ServerSubscriptionHandle ss, const SipMessage& msg)
00474 {
00475    InfoLog(<< "onRefer: msg=" << msg.brief());
00476 
00477    // Handle Refer request here
00478 }
00479 
00480 void
00481 BasicClientCall::onReferAccepted(InviteSessionHandle h, ClientSubscriptionHandle csh, const SipMessage& msg)
00482 {
00483    InfoLog(<< "onReferAccepted: msg=" << msg.brief());
00484 }
00485 
00486 void
00487 BasicClientCall::onReferRejected(InviteSessionHandle h, const SipMessage& msg)
00488 {
00489    WarningLog(<< "onReferRejected: msg=" << msg.brief());
00490 }
00491 
00492 void
00493 BasicClientCall::onReferNoSub(InviteSessionHandle h, const SipMessage& msg)
00494 {
00495    InfoLog(<< "onReferNoSub: msg=" << msg.brief());
00496 
00497    // Handle Refer request with (no-subscription indication) here
00498 }
00499 
00500 void
00501 BasicClientCall::onMessage(InviteSessionHandle h, const SipMessage& msg)
00502 {
00503    InfoLog(<< "onMessage: msg=" << msg.brief());
00504 
00505    // Handle message here
00506    h->acceptNIT();
00507 
00508    if(!mPlacedCall)
00509    {
00510       // If we didn't place the call - answer the message with another message
00511       PlainContents plain("test message answer");
00512       h->message(plain);
00513    }
00514 }
00515 
00516 void
00517 BasicClientCall::onMessageSuccess(InviteSessionHandle h, const SipMessage& msg)
00518 {
00519    InfoLog(<< "onMessageSuccess: msg=" << msg.brief());
00520 }
00521 
00522 void
00523 BasicClientCall::onMessageFailure(InviteSessionHandle h, const SipMessage& msg)
00524 {
00525    WarningLog(<< "onMessageFailure: msg=" << msg.brief());
00526 }
00527 
00528 void
00529 BasicClientCall::onForkDestroyed(ClientInviteSessionHandle h)
00530 {
00531    InfoLog(<< "onForkDestroyed:");
00532 }
00533 
00534 void 
00535 BasicClientCall::onReadyToSend(InviteSessionHandle h, SipMessage& msg)
00536 {
00537 }
00538 
00539 void 
00540 BasicClientCall::onFlowTerminated(InviteSessionHandle h)
00541 {
00542    if(h->isConnected())
00543    {
00544       NameAddr inviteWithReplacesTarget;
00545       if(h->remoteTarget().uri().exists(p_gr))
00546       {
00547          // If remote contact is a GRUU then use it
00548          inviteWithReplacesTarget.uri() = h->remoteTarget().uri();
00549       }
00550       else
00551       {
00552          //.Use remote AOR
00553          inviteWithReplacesTarget.uri() = h->peerAddr().uri();
00554       }
00555       InfoLog(<< "BasicClientCall::onFlowTerminated: trying INVITE w/replaces to " << inviteWithReplacesTarget);
00556       // The flow terminated - try an Invite (with Replaces) to recover the call
00557       BasicClientCall *replacesCall = new BasicClientCall(mUserAgent);      
00558 
00559       // Copy over flag that indicates wether original call was placed or received
00560       replacesCall->mPlacedCall = mPlacedCall;  
00561 
00562       // Note:  We want to end this call since it is to be replaced.  Normally the endpoint
00563       // receiving the INVITE with replaces would send us a BYE for the session being replaced.
00564       // However, since the old flow is dead, we will never see this BYE.  We need this call to
00565       // go away somehow, however we cannot just end it directly here via terminateCall.
00566       // Since the flow to other party is likely fine - if we terminate this call now the BYE 
00567       // is very likely to make it to the far end, before the above INVITE - if this happens then 
00568       // the replaces logic of the INVITE will have no effect.  We want to delay the release of 
00569       // this call, by passing our handle to the new INVITE call and have it terminate this call, 
00570       // once we know the far end has processed our new INVITE.
00571       replacesCall->mInviteSessionHandleReplaced = mInviteSessionHandle;
00572 
00573       SdpContents offer;
00574       replacesCall->makeOffer(offer);
00575       SharedPtr<SipMessage> invite = mUserAgent.getDialogUsageManager().makeInviteSession(inviteWithReplacesTarget, h, getUserProfile(), &offer, replacesCall);
00576       mUserAgent.getDialogUsageManager().send(invite);
00577    }
00578 }
00579 
00581 // DialogSetHandler ///////////////////////////////////////////////////
00583 void 
00584 BasicClientCall::onTrying(AppDialogSetHandle h, const SipMessage& msg)
00585 {
00586    InfoLog(<< "onTrying: msg=" << msg.brief());
00587    if(isUACConnected()) return;  // Ignore 100's if already connected
00588 
00589    // Handle message here
00590 }
00591 
00592 void 
00593 BasicClientCall::onNonDialogCreatingProvisional(AppDialogSetHandle h, const SipMessage& msg)
00594 {
00595    InfoLog(<< "onNonDialogCreatingProvisional: msg=" << msg.brief());
00596    if(isUACConnected()) return;  // Ignore provionals if already connected
00597 
00598    // Handle message here
00599 }
00600 
00602 // ClientSubscriptionHandler ///////////////////////////////////////////////////
00604 void
00605 BasicClientCall::onUpdatePending(ClientSubscriptionHandle h, const SipMessage& msg, bool outOfOrder)
00606 {
00607    InfoLog(<< "onUpdatePending(ClientSubscriptionHandle): " << msg.brief());
00608    if (msg.exists(h_Event) && msg.header(h_Event).value() == "refer")
00609    {
00610       //process Refer Notify Here
00611    }
00612    h->acceptUpdate();
00613 }
00614 
00615 void
00616 BasicClientCall::onUpdateActive(ClientSubscriptionHandle h, const SipMessage& msg, bool outOfOrder)
00617 {
00618    InfoLog(<< "onUpdateActive(ClientSubscriptionHandle): " << msg.brief());
00619    if (msg.exists(h_Event) && msg.header(h_Event).value() == "refer")
00620    {
00621       //process Refer Notify Here
00622    }
00623    h->acceptUpdate();
00624 }
00625 
00626 void
00627 BasicClientCall::onUpdateExtension(ClientSubscriptionHandle h, const SipMessage& msg, bool outOfOrder)
00628 {
00629    InfoLog(<< "onUpdateExtension(ClientSubscriptionHandle): " << msg.brief());
00630    if (msg.exists(h_Event) && msg.header(h_Event).value() == "refer")
00631    {
00632       //process Refer Notify Here
00633    }
00634    h->acceptUpdate();
00635 }
00636 
00637 void 
00638 BasicClientCall::onNotifyNotReceived(resip::ClientSubscriptionHandle h)
00639 {
00640    InfoLog(<< "onNotifyNotReceived(ClientSubscriptionHandle)");
00641    h->end();
00642 }
00643 
00644 void
00645 BasicClientCall::onTerminated(ClientSubscriptionHandle h, const SipMessage* msg)
00646 {
00647    if(msg)
00648    {
00649       InfoLog(<< "onTerminated(ClientSubscriptionHandle): " << msg->brief());
00650       //Note:  Final notify is sometimes only passed in the onTerminated callback
00651       if (msg->isRequest() && msg->exists(h_Event) && msg->header(h_Event).value() == "refer")
00652       {
00653          //process Refer Notify Here
00654       }
00655    }
00656    else
00657    {
00658       InfoLog(<< "onTerminated(ClientSubscriptionHandle)");
00659    }
00660 }
00661 
00662 void
00663 BasicClientCall::onNewSubscription(ClientSubscriptionHandle h, const SipMessage& msg)
00664 {
00665    InfoLog(<< "onNewSubscription(ClientSubscriptionHandle): " << msg.brief());
00666 }
00667 
00668 int 
00669 BasicClientCall::onRequestRetry(ClientSubscriptionHandle h, int retrySeconds, const SipMessage& msg)
00670 {
00671    InfoLog(<< "onRequestRetry(ClientSubscriptionHandle): " << msg.brief());
00672    return -1;
00673 }
00674 
00675 void 
00676 BasicClientCall::onRedirectReceived(AppDialogSetHandle h, const SipMessage& msg)
00677 {
00678    InfoLog(<< "onRedirectReceived: msg=" << msg.brief());
00679 }
00680 
00681 
00682 /* ====================================================================
00683 
00684  Copyright (c) 2011, SIP Spectrum, Inc.
00685  All rights reserved.
00686 
00687  Redistribution and use in source and binary forms, with or without
00688  modification, are permitted provided that the following conditions are 
00689  met:
00690 
00691  1. Redistributions of source code must retain the above copyright 
00692     notice, this list of conditions and the following disclaimer. 
00693 
00694  2. Redistributions in binary form must reproduce the above copyright
00695     notice, this list of conditions and the following disclaimer in the
00696     documentation and/or other materials provided with the distribution. 
00697 
00698  3. Neither the name of SIP Spectrum nor the names of its contributors 
00699     may be used to endorse or promote products derived from this 
00700     software without specific prior written permission. 
00701 
00702  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
00703  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
00704  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
00705  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
00706  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
00707  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
00708  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
00709  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
00710  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
00711  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
00712  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00713 
00714  ==================================================================== */