|
reSIProcate/DialogUsageManager
9694
|
00001 #include "resip/dum/AppDialog.hxx" 00002 #include "resip/dum/Dialog.hxx" 00003 #include "resip/dum/DialogUsageManager.hxx" 00004 #include "resip/dum/ServerSubscription.hxx" 00005 #include "resip/dum/SubscriptionHandler.hxx" 00006 #include "resip/dum/UsageUseException.hxx" 00007 #include "resip/stack/Helper.hxx" 00008 #include "rutil/Logger.hxx" 00009 00010 #include <time.h> 00011 00012 using namespace resip; 00013 00014 #define RESIPROCATE_SUBSYSTEM Subsystem::DUM 00015 00016 ServerSubscriptionHandle 00017 ServerSubscription::getHandle() 00018 { 00019 return ServerSubscriptionHandle(mDum, getBaseHandle().getId()); 00020 } 00021 00022 ServerSubscription::ServerSubscription(DialogUsageManager& dum, 00023 Dialog& dialog, 00024 const SipMessage& req) 00025 : BaseSubscription(dum, dialog, req), 00026 mSubscriber(req.header(h_From).uri().getAor()), 00027 mExpires(60), 00028 mAbsoluteExpiry(0) 00029 { 00030 if (req.header(h_RequestLine).method() == REFER && req.header(h_To).exists(p_tag)) 00031 { 00032 // If this is an in-dialog REFER, then use a subscription id 00033 mSubscriptionId = Data(req.header(h_CSeq).sequence()); 00034 } 00035 Data key = getEventType() + getDocumentKey(); 00036 mDum.mServerSubscriptions.insert(DialogUsageManager::ServerSubscriptions::value_type(key, this)); 00037 } 00038 00039 ServerSubscription::~ServerSubscription() 00040 { 00041 DebugLog(<< "ServerSubscription::~ServerSubscription"); 00042 00043 Data key = getEventType() + getDocumentKey(); 00044 00045 std::pair<DialogUsageManager::ServerSubscriptions::iterator,DialogUsageManager::ServerSubscriptions::iterator> subs; 00046 subs = mDum.mServerSubscriptions.equal_range(key); 00047 for (DialogUsageManager::ServerSubscriptions::iterator i=subs.first; i!=subs.second; ++i) 00048 { 00049 if (i->second == this) 00050 { 00051 mDum.mServerSubscriptions.erase(i); 00052 break; 00053 } 00054 } 00055 00056 mDialog.mServerSubscriptions.remove(this); 00057 } 00058 00059 UInt32 00060 ServerSubscription::getTimeLeft() 00061 { 00062 UInt32 timeleft = UInt32(mAbsoluteExpiry - Timer::getTimeSecs()); 00063 if (timeleft < 0) // .kw. this can NEVER happen since unsigned! 00064 { 00065 return 0; 00066 } 00067 else 00068 { 00069 return timeleft; 00070 } 00071 } 00072 00073 SharedPtr<SipMessage> 00074 ServerSubscription::accept(int statusCode) 00075 { 00076 mDialog.makeResponse(*mLastResponse, mLastSubscribe, statusCode); 00077 mLastResponse->header(h_Expires).value() = mExpires; 00078 return mLastResponse; 00079 } 00080 00081 SharedPtr<SipMessage> 00082 ServerSubscription::reject(int statusCode) 00083 { 00084 if (statusCode < 300) 00085 { 00086 throw UsageUseException("Must reject with a code greater than or equal to 300", __FILE__, __LINE__); 00087 } 00088 mDialog.makeResponse(*mLastResponse, mLastSubscribe, statusCode); 00089 return mLastResponse; 00090 } 00091 00092 00093 void 00094 ServerSubscription::send(SharedPtr<SipMessage> msg) 00095 { 00096 ServerSubscriptionHandler* handler = mDum.getServerSubscriptionHandler(mEventType); 00097 assert(handler); 00098 if (msg->isResponse()) 00099 { 00100 int code = msg->header(h_StatusLine).statusCode(); 00101 if (code < 200) 00102 { 00103 DialogUsage::send(msg); 00104 } 00105 else if (code < 300) 00106 { 00107 if(msg->exists(h_Expires)) 00108 { 00109 mDum.addTimer(DumTimeout::Subscription, msg->header(h_Expires).value(), getBaseHandle(), ++mTimerSeq); 00110 DialogUsage::send(msg); 00111 mAbsoluteExpiry = Timer::getTimeSecs() + msg->header(h_Expires).value(); 00112 mSubDlgState = SubDlgEstablished; 00113 } 00114 else 00115 { 00116 throw UsageUseException("2xx to a Subscribe MUST contain an Expires header", __FILE__, __LINE__); 00117 } 00118 } 00119 else if (code < 400) 00120 { 00121 DialogUsage::send(msg); 00122 handler->onTerminated(getHandle()); 00123 delete this; 00124 return; 00125 } 00126 else 00127 { 00128 if (shouldDestroyAfterSendingFailure(*msg)) 00129 { 00130 DialogUsage::send(msg); 00131 handler->onTerminated(getHandle()); 00132 delete this; 00133 return; 00134 } 00135 else 00136 { 00137 DialogUsage::send(msg); 00138 } 00139 } 00140 } 00141 else 00142 { 00143 DialogUsage::send(msg); 00144 if (mSubscriptionState == Terminated) 00145 { 00146 handler->onTerminated(getHandle()); 00147 delete this; 00148 } 00149 } 00150 } 00151 00152 bool 00153 ServerSubscription::shouldDestroyAfterSendingFailure(const SipMessage& msg) 00154 { 00155 int code = msg.header(h_StatusLine).statusCode(); 00156 switch(mSubDlgState) 00157 { 00158 case SubDlgInitial: 00159 return true; 00160 case SubDlgTerminating: //terminated state not using in ServerSubscription 00161 assert(0); 00162 return true; 00163 case SubDlgEstablished: 00164 { 00165 if (code == 405) 00166 { 00167 return true; 00168 } 00169 switch (Helper::determineFailureMessageEffect(*mLastResponse)) 00170 { 00171 case Helper::TransactionTermination: 00172 case Helper::RetryAfter: 00173 break; 00174 case Helper::OptionalRetryAfter: 00175 case Helper::ApplicationDependant: 00176 // .bwc. Uh, no. ApplicationDependent should imply that the 00177 // app-writer has decided what to do. We don't decide here. And 00178 // OptionalRetryAfter certainly doesn't mean we should tear the 00179 // Usage down. 00180 // throw UsageUseException("Not a reasonable code to reject a SUBSCIRBE(refresh) inside a dialog.", 00181 // __FILE__, __LINE__); 00182 break; 00183 case Helper::DialogTermination: //?dcm? -- throw or destroy this? 00184 case Helper::UsageTermination: 00185 return true; 00186 } 00187 break; 00188 } 00189 default: // !jf! 00190 assert(0); 00191 break; 00192 00193 } 00194 return false; 00195 } 00196 00197 void 00198 ServerSubscription::setSubscriptionState(SubscriptionState state) 00199 { 00200 mSubscriptionState = state; 00201 } 00202 00203 void 00204 ServerSubscription::dispatch(const SipMessage& msg) 00205 { 00206 DebugLog( << "ServerSubscriptionHandler::dispatch: " << msg.brief()); 00207 00208 ServerSubscriptionHandler* handler = mDum.getServerSubscriptionHandler(mEventType); 00209 assert(handler); 00210 00211 if (msg.isRequest()) 00212 { 00214 //expiration times for an event package--part of handler API? 00215 //added to handler for now. 00216 mLastSubscribe = msg; 00217 00218 int errorResponseCode = 0; 00219 handler->getExpires(msg,mExpires,errorResponseCode); 00220 if (errorResponseCode >= 400) 00221 { 00222 handler->onError(getHandle(), msg); 00223 SharedPtr<SipMessage> response = reject(errorResponseCode); 00224 00225 if (errorResponseCode == 423 && handler->hasMinExpires()) 00226 { 00227 response->header(h_MinExpires).value() = handler->getMinExpires(); 00228 } 00229 send(response); 00230 return; 00231 } 00232 00233 InviteSessionHandle invSession; 00234 if (getAppDialog().isValid()) 00235 { 00236 invSession = getAppDialog()->getInviteSession(); 00237 } 00238 00239 if (mExpires == 0) 00240 { 00241 /* This is to handle the case where mExpires is zero because the client 00242 is attempting to poll. In order for polling to work, the subscription 00243 handler needs to get the onNewSubscription call. .mjf. 00244 */ 00245 if (mSubscriptionState == Invalid) 00246 { 00247 mSubscriptionState = Terminated; 00248 if (mEventType != "refer" ) 00249 { 00250 handler->onNewSubscription(getHandle(), msg); 00251 } 00252 else if (!invSession.isValid()) 00253 { 00254 handler->onNewSubscriptionFromRefer(getHandle(), msg); 00255 } 00256 } 00257 00258 makeNotifyExpires(); 00259 handler->onExpiredByClient(getHandle(), msg, *mLastRequest); 00260 00261 mDialog.makeResponse(*mLastResponse, mLastSubscribe, 200); 00262 mLastResponse->header(h_Expires).value() = mExpires; 00263 send(mLastResponse); 00264 00265 send(mLastRequest); // Send Notify Expires 00266 return; 00267 } 00268 if (mSubscriptionState == Invalid) 00269 { 00271 mSubscriptionState = Init; 00272 if (mEventType != "refer") 00273 { 00274 DebugLog(<< "onNewSubscription called"); 00275 handler->onNewSubscription(getHandle(), msg); 00276 } 00277 else if (!invSession.isValid()) 00278 { 00279 DebugLog(<< "onNewSubscriptionFromRefer called"); 00280 handler->onNewSubscriptionFromRefer(getHandle(), msg); 00281 } 00282 } 00283 else 00284 { 00285 DebugLog(<< "onRefresh called"); 00286 handler->onRefresh(getHandle(), msg); 00287 } 00288 } 00289 else 00290 { 00291 //.dcm. - will need to change if retry-afters are reaching here 00292 mLastRequest->releaseContents(); 00293 int code = msg.header(h_StatusLine).statusCode(); 00294 if (code < 300) 00295 { 00296 return; 00297 } 00298 else if (code < 400) 00299 { 00300 //in dialog NOTIFY got redirected? Bizarre... 00301 handler->onError(getHandle(), msg); 00302 handler->onTerminated(getHandle()); 00303 delete this; 00304 } 00305 else 00306 { 00307 switch(Helper::determineFailureMessageEffect(msg)) 00308 { 00309 case Helper::TransactionTermination: 00310 DebugLog( << "ServerSubscriptionHandler::TransactionTermination: " << msg.brief()); 00311 handler->onNotifyRejected(getHandle(), msg); 00312 break; 00313 case Helper::UsageTermination: 00314 case Helper::RetryAfter: 00315 case Helper::OptionalRetryAfter: 00316 case Helper::ApplicationDependant: 00317 case Helper::DialogTermination: 00318 DebugLog( << "ServerSubscriptionHandler::UsageTermination: " << msg.brief()); 00319 handler->onError(getHandle(), msg); 00320 handler->onTerminated(getHandle()); 00321 delete this; 00322 break; 00323 } 00324 } 00325 } 00326 } 00327 00328 void 00329 ServerSubscription::makeNotifyExpires() 00330 { 00331 mSubscriptionState = Terminated; 00332 makeNotify(); 00333 mLastRequest->header(h_SubscriptionState).param(p_reason) = getTerminateReasonString(Timeout); 00334 } 00335 00336 void 00337 ServerSubscription::makeNotify() 00338 { 00339 mDialog.makeRequest(*mLastRequest, NOTIFY); 00340 mLastRequest->header(h_SubscriptionState).value() = getSubscriptionStateString(mSubscriptionState); 00341 if (mSubscriptionState == Terminated) 00342 { 00343 mLastRequest->header(h_SubscriptionState).remove(p_expires); 00344 } 00345 else 00346 { 00347 mLastRequest->header(h_SubscriptionState).param(p_expires) = getTimeLeft(); 00348 } 00349 00350 mLastRequest->header(h_Event).value() = mEventType; 00351 if (!mSubscriptionId.empty()) 00352 { 00353 mLastRequest->header(h_Event).param(p_id) = mSubscriptionId; 00354 } 00355 } 00356 00357 00358 void 00359 ServerSubscription::end(TerminateReason reason, const Contents* document) 00360 { 00361 mSubscriptionState = Terminated; 00362 makeNotify(); 00363 mLastRequest->header(h_SubscriptionState).param(p_reason) = getTerminateReasonString(reason); 00364 if (document) 00365 { 00366 mLastRequest->setContents(document); 00367 } 00368 send(mLastRequest); 00369 } 00370 00371 void 00372 ServerSubscription::end() 00373 { 00374 end(Timeout); 00375 } 00376 00377 void 00378 ServerSubscription::dispatch(const DumTimeout& timeout) 00379 { 00380 assert(timeout.type() == DumTimeout::Subscription); 00381 if (timeout.seq() == mTimerSeq) 00382 { 00383 ServerSubscriptionHandler* handler = mDum.getServerSubscriptionHandler(mEventType); 00384 assert(handler); 00385 makeNotifyExpires(); 00386 handler->onExpired(getHandle(), *mLastRequest); 00387 send(mLastRequest); 00388 } 00389 } 00390 00391 SharedPtr<SipMessage> 00392 ServerSubscription::update(const Contents* document) 00393 { 00394 makeNotify(); 00395 mLastRequest->setContents(document); 00396 return mLastRequest; 00397 } 00398 00399 SharedPtr<SipMessage> 00400 ServerSubscription::neutralNotify() 00401 { 00402 makeNotify(); 00403 mLastRequest->releaseContents(); 00404 return mLastRequest; 00405 } 00406 00407 void 00408 ServerSubscription::dialogDestroyed(const SipMessage& msg) 00409 { 00410 ServerSubscriptionHandler* handler = mDum.getServerSubscriptionHandler(mEventType); 00411 assert(handler); 00412 handler->onError(getHandle(), msg); 00413 handler->onTerminated(getHandle()); 00414 delete this; 00415 } 00416 00417 void 00418 ServerSubscription::onReadyToSend(SipMessage& msg) 00419 { 00420 ServerSubscriptionHandler* handler = mDum.getServerSubscriptionHandler(mEventType); 00421 assert(handler); 00422 handler->onReadyToSend(getHandle(), msg); 00423 } 00424 00425 void 00426 ServerSubscription::flowTerminated() 00427 { 00428 // notify handler 00429 ServerSubscriptionHandler* handler = mDum.getServerSubscriptionHandler(mEventType); 00430 assert(handler); 00431 handler->onFlowTerminated(getHandle()); 00432 } 00433 00434 EncodeStream& 00435 ServerSubscription::dump(EncodeStream& strm) const 00436 { 00437 strm << "ServerSubscription " << mSubscriber; 00438 return strm; 00439 } 00440 00441 00442 /* ==================================================================== 00443 * The Vovida Software License, Version 1.0 00444 * 00445 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00446 * 00447 * Redistribution and use in source and binary forms, with or without 00448 * modification, are permitted provided that the following conditions 00449 * are met: 00450 * 00451 * 1. Redistributions of source code must retain the above copyright 00452 * notice, this list of conditions and the following disclaimer. 00453 * 00454 * 2. Redistributions in binary form must reproduce the above copyright 00455 * notice, this list of conditions and the following disclaimer in 00456 * the documentation and/or other materials provided with the 00457 * distribution. 00458 * 00459 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00460 * and "Vovida Open Communication Application Library (VOCAL)" must 00461 * not be used to endorse or promote products derived from this 00462 * software without prior written permission. For written 00463 * permission, please contact vocal@vovida.org. 00464 * 00465 * 4. Products derived from this software may not be called "VOCAL", nor 00466 * may "VOCAL" appear in their name, without prior written 00467 * permission of Vovida Networks, Inc. 00468 * 00469 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00470 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00471 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00472 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00473 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00474 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00475 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00476 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00477 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00478 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00479 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00480 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00481 * DAMAGE. 00482 * 00483 * ==================================================================== 00484 * 00485 * This software consists of voluntary contributions made by Vovida 00486 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00487 * Inc. For more information on Vovida Networks, Inc., please see 00488 * <http://www.vovida.org/>. 00489 * 00490 */
1.7.5.1