[reSIProcate] Restoring subscription in DUM
- From: Volodymyr Tarasenko <tvntsr@xxxxxxxxx>
- Date: Mon, 26 Apr 2010 12:32:13 -0700 (PDT)
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);