< Previous by Date Date Index Next by Date >
  Thread Index  

[reSIProcate] Restoring subscription in DUM


Hi,

As I see there is no way to restore subscriptions after application 
restart/shutdown. So, I'd like to add the next method to DUM:
    bool feedSubscription(const resip::SipMessage& subscr);

Also, it is useful to handle subscription restoring in 
ServerSubscriptionHandler:
    virtual void onFeed(ServerSubscriptionHandle, const SipMessage&)

The patch to implement it is in attachment.

Regards,
Volodymyr!


      
--- resip/dum/Dialog.cxx
+++ resip/dum/Dialog.cxx
@@ -362,6 +362,33 @@
    }
 }
 
+bool 
+Dialog::feed(const SipMessage& request)
+{
+    ServerSubscription* server = findMatchingServerSub(request);
+    if (!server)
+    {
+        //server->dispatch(request);
+        if (request.exists(h_Event) && 
+            request.header(h_Event).value() == "refer")
+        {
+            return false;
+        }
+        else
+        {
+            if (!mDum.checkEventPackage(request))
+            {
+                return false;
+            }
+
+            server = makeServerSubscription(request);
+            mServerSubscriptions.push_back(server);
+        }
+    }
+
+    return server->feed(request);
+}
+
 void
 Dialog::dispatch(const SipMessage& msg)
 {
--- resip/dum/Dialog.hxx
+++ resip/dum/Dialog.hxx
@@ -98,6 +98,9 @@
       friend class ServerOutOfDialogReq;
 
       friend class AppDialog;
+
+      virtual bool feed(const SipMessage& request);
+
       void possiblyDie();
 
       ClientSubscription* findMatchingClientSub(const SipMessage& msg);
--- resip/dum/DialogSet.cxx
+++ resip/dum/DialogSet.cxx
@@ -309,6 +309,39 @@
    return false;
 }
 
+bool
+DialogSet::feed(const SipMessage& request)
+{
+    Dialog* dialog = 0;
+
+    DialogMap::iterator i = mDialogs.find(DialogId(request));
+    if (i != mDialogs.end())
+    {
+        dialog = i->second;
+    }
+
+    if (!dialog)
+    {
+        DebugLog ( << "mState == " << mState 
+                   << " Creating a new Dialog from msg: "
+                   << std::endl << std::endl 
+                   << request);
+
+        dialog = new Dialog(mDum, request, *this);
+    
+        assert(mState != WaitingToEnd);
+
+        DebugLog ( << "### Calling CreateAppDialog ###: " 
+                   << std::endl << std::endl 
+                   << request);
+        
+        AppDialog* appDialog = mAppDialogSet->createAppDialog(request);
+        dialog->mAppDialog   = appDialog;
+        appDialog->mDialog   = dialog;
+    }
+
+    return dialog->feed(request);
+}
 
 void
 DialogSet::dispatch(const SipMessage& msg)
--- resip/dum/DialogSet.hxx
+++ resip/dum/DialogSet.hxx
@@ -97,7 +97,9 @@
       ServerRegistration* makeServerRegistration(const SipMessage& msg);
       ServerOutOfDialogReq* makeServerOutOfDialog(const SipMessage& msg);
       
-      ServerPagerMessage* makeServerPagerMessage(const SipMessage& request);      
+      ServerPagerMessage* makeServerPagerMessage(const SipMessage& request);
+
+      virtual bool feed(const SipMessage& request);
 
       void dispatchToAllDialogs(const SipMessage& msg);      
 
--- resip/dum/DialogUsageManager.cxx
+++ resip/dum/DialogUsageManager.cxx
@@ -203,6 +203,57 @@
    return mStack.getHostAddress();
 }
 
+bool
+DialogUsageManager::feedSubscription(const resip::SipMessage& request)
+{
+    if (request.header(h_RequestLine).getMethod() != SUBSCRIBE)
+        return false;
+
+    {
+        DialogSetId id(request);
+        //cryptographically dangerous
+        if(mDialogSetMap.find(id) != mDialogSetMap.end()) 
+        {
+            // this can only happen if someone sends us a request with the same 
+            // callid and from tag as one that is in the process of 
+            // destroying - since this is bad endpoint behaviour - we will 
+            // reject the request with a 400 response
+            return false;
+        }
+    }
+
+    try
+    {
+        DialogSet* dset =  new DialogSet(request, *this);
+
+        StackLog ( << "*********** Calling AppDialogSetFactory *************" );
+
+        AppDialogSet* appDs 
+                = mAppDialogSetFactory->createAppDialogSet(*this, request);
+
+        appDs->mDialogSet = dset;
+        dset->setUserProfile(appDs->selectUASUserProfile(request));
+        dset->mAppDialogSet = appDs;
+
+        StackLog ( << "************* Adding DialogSet ***************" );
+        StackLog ( << "Before: " << Inserter(mDialogSetMap) );
+        
+        mDialogSetMap[dset->getId()] = dset;
+        
+        StackLog ( << "After: Req" << Inserter(mDialogSetMap) );
+
+        return dset->feed(request);
+    }
+    catch (BaseException& e)
+    {
+        StackLog(<< "Error in feeding: " << e.what());
+        
+        return false;
+    }
+
+    // never reach this point
+}
+
 void
 DialogUsageManager::onAllHandlesDestroyed()
 {
--- resip/dum/DialogUsageManager.hxx
+++ resip/dum/DialogUsageManager.hxx
@@ -121,7 +121,8 @@
 
       SipStack& getSipStack();
       Security* getSecurity();
-      
+      bool feedSubscription(const resip::SipMessage& subscr);
+    
       Data getHostAddress();
 
       void setAppDialogSetFactory(std::auto_ptr<AppDialogSetFactory>);
--- resip/dum/ServerSubscription.cxx
+++ resip/dum/ServerSubscription.cxx
@@ -190,6 +190,71 @@
    mSubscriptionState = state;
 }
 
+bool
+ServerSubscription::feed(const SipMessage& request)
+{
+    DebugLog( << "ServerSubscriptionHandler::feed: " << request.brief());
+
+    ServerSubscriptionHandler* handler 
+            = mDum.getServerSubscriptionHandler(mEventType);
+    assert(handler);
+
+    if (!request.isRequest())
+    {    
+        return false;
+    }
+     
+    //!dcm! -- need to have a mechanism to retrieve default & acceptable
+    //expiration times for an event package--part of handler API?
+    //added to handler for now.
+    mLastSubscribe = request;
+   
+    int errorResponseCode = 0;
+
+    handler->getExpires(request, mExpires, errorResponseCode);
+
+    if (errorResponseCode >= 400)
+    {
+        return false;
+    }     
+
+    InviteSessionHandle invSession;
+    if (getAppDialog().isValid())
+    {
+        invSession = getAppDialog()->getInviteSession();
+    }
+
+    if (mExpires == 0)
+    {
+        /* This is to handle the case where mExpires is zero because the client
+           is attempting to poll.  In order for polling to work, the 
+           subscription handler needs to get the onNewSubscription call. .mjf.
+        */
+        if (mSubscriptionState == Invalid)
+        {
+            mSubscriptionState = Terminated;
+        }
+
+        makeNotifyExpires();
+        handler->onExpiredByClient(getHandle(), request, *mLastRequest);
+         
+        mDialog.makeResponse(*mLastResponse, mLastSubscribe, 200);
+        mLastResponse->header(h_Expires).value() = mExpires;
+        send(mLastResponse);
+        end(Timeout);
+        return true;
+    }
+    
+    if (mSubscriptionState == Invalid)
+    {
+        //!dcm! -- should initial state be pending?
+        mSubscriptionState = Init;
+    }
+    
+    handler->onFeed(getHandle(), request);
+    return true;
+}
+
 void 
 ServerSubscription::dispatch(const SipMessage& msg)
 {
--- resip/dum/ServerSubscription.hxx
+++ resip/dum/ServerSubscription.hxx
@@ -43,6 +43,8 @@
 
       virtual EncodeStream& dump(EncodeStream& strm) const;
 
+      virtual bool feed(const SipMessage& request);
+
    protected:
       virtual ~ServerSubscription();
       virtual void dialogDestroyed(const SipMessage& msg);           
--- resip/dum/SubscriptionHandler.hxx
+++ resip/dum/SubscriptionHandler.hxx
@@ -38,6 +38,9 @@
   public:   
       virtual ~ServerSubscriptionHandler() {}
 
+      virtual void onFeed(ServerSubscriptionHandle, const SipMessage&)
+      {}
+
       virtual void onNewSubscription(ServerSubscriptionHandle, const SipMessage& sub)=0;
       virtual void onNewSubscriptionFromRefer(ServerSubscriptionHandle, const SipMessage& sub);
       virtual void onRefresh(ServerSubscriptionHandle, const SipMessage& sub);