|
reSIProcate/DialogUsageManager
9694
|
00001 #include "resip/stack/ExtensionParameter.hxx" 00002 #include "resip/stack/InteropHelper.hxx" 00003 #include "resip/stack/SipMessage.hxx" 00004 #include "resip/stack/Helper.hxx" 00005 #include "resip/dum/DialogUsageManager.hxx" 00006 #include "resip/dum/MasterProfile.hxx" 00007 #include "resip/dum/ServerRegistration.hxx" 00008 #include "resip/dum/Dialog.hxx" 00009 #include "resip/dum/RegistrationHandler.hxx" 00010 #include "resip/dum/RegistrationPersistenceManager.hxx" 00011 #include "rutil/DnsUtil.hxx" 00012 #include "rutil/Logger.hxx" 00013 #include "rutil/Timer.hxx" 00014 #include "rutil/WinLeakCheck.hxx" 00015 00016 #define RESIPROCATE_SUBSYSTEM Subsystem::DUM 00017 00018 using namespace resip; 00019 00020 ServerRegistrationHandle 00021 ServerRegistration::getHandle() 00022 { 00023 return ServerRegistrationHandle(mDum, getBaseHandle().getId()); 00024 } 00025 00026 ServerRegistration::ServerRegistration(DialogUsageManager& dum, DialogSet& dialogSet, const SipMessage& request) 00027 : NonDialogUsage(dum, dialogSet), 00028 mRequest(request), 00029 mDidOutbound(false), 00030 mAsyncState(asyncStateNone) 00031 {} 00032 00033 ServerRegistration::~ServerRegistration() 00034 { 00035 mDialogSet.mServerRegistration = 0; 00036 } 00037 00038 void 00039 ServerRegistration::end() 00040 { 00041 } 00042 00043 static Token outbound(Symbols::Outbound); 00044 void 00045 ServerRegistration::accept(SipMessage& ok) 00046 { 00047 ok.remove(h_Contacts); 00048 00049 InfoLog( << "accepted a registration " << mAor ); 00050 00051 if (mDidOutbound) 00052 { 00053 ok.header(h_Requires).push_back(outbound); 00054 if(InteropHelper::getFlowTimerSeconds() > 0) 00055 { 00056 ok.header(h_FlowTimer).value() = InteropHelper::getFlowTimerSeconds(); 00057 mDum.getSipStack().enableFlowTimer(mRequest.getSource()); 00058 } 00059 } 00060 00061 if (!mDum.mServerRegistrationHandler->asyncProcessing()) 00062 { 00063 // Add all registered contacts to the message. 00064 RegistrationPersistenceManager *database = mDum.mRegistrationPersistenceManager; 00065 00066 ContactList contacts; 00067 database->getContacts(mAor, contacts); 00068 00069 //removes expired entries from the ok msg as well as calls the database to remove expired contacts. 00070 processFinalOkMsg(ok,contacts); 00071 00072 database->unlockRecord(mAor); 00073 00074 SharedPtr<SipMessage> msg(static_cast<SipMessage*>(ok.clone())); 00075 mDum.send(msg); 00076 delete(this); 00077 } 00078 else 00079 { 00080 if (mAsyncState == asyncStateQueryOnly) 00081 { 00082 if (!mAsyncLocalStore.get()) 00083 { 00084 assert(0); 00085 } 00086 else 00087 { 00088 std::auto_ptr<ContactRecordTransactionLog> log; 00089 std::auto_ptr<ContactPtrList> contacts; 00090 00091 mAsyncLocalStore->releaseLog(log,contacts); 00092 00093 if (contacts.get()) 00094 { 00095 asyncProcessFinalOkMsg(ok,*contacts); 00096 } 00097 } 00098 00099 SharedPtr<SipMessage> msg(static_cast<SipMessage*>(ok.clone())); 00100 mDum.send(msg); 00101 delete(this); 00102 } 00103 else 00104 { 00105 if (!mAsyncLocalStore.get()) 00106 { 00107 assert(0); 00108 return; 00109 } 00110 //This register was accepted, but still need to apply the changes made by this register and then 00111 //receive a final contact list before sending the 200. 00112 mAsyncState = asyncStateAcceptedWaitingForFinalContactList; 00113 00114 std::auto_ptr<ContactRecordTransactionLog> log; 00115 std::auto_ptr<ContactPtrList> modifiedContacts; 00116 00117 mAsyncLocalStore->releaseLog(log,modifiedContacts); 00118 00119 mAsyncOkMsg = SharedPtr<SipMessage>(static_cast<SipMessage*>(ok.clone())); 00120 mDum.mServerRegistrationHandler->asyncUpdateContacts(getHandle(),mAor,modifiedContacts,log); 00122 return; 00123 } 00124 } 00125 } 00126 00127 void 00128 ServerRegistration::accept(int statusCode) 00129 { 00130 SipMessage success; 00131 mDum.makeResponse(success, mRequest, statusCode); 00132 // .bwc. Copy Path headers if present, indicate Path support 00133 // ?bwc? If path headers are present, but client indicates no path support, 00134 // RFC 3327 says it is a matter of policy of whether to accept the 00135 // registration or not. What should we do here? Is it worth it to make this 00136 // configurable? 00137 if(!mRequest.empty(h_Paths)) 00138 { 00139 success.header(h_Paths)=mRequest.header(h_Paths); 00140 success.header(h_Supporteds).push_back(Token(Symbols::Path)); 00141 } 00142 accept(success); 00143 } 00144 00145 void 00146 ServerRegistration::reject(int statusCode) 00147 { 00148 InfoLog( << "rejected a registration " << mAor << " with statusCode=" << statusCode ); 00149 00150 // First, we roll back the contact database to 00151 // the state it was before the registration request. 00152 00153 // Async processing hasn't actually updated the database yet, so no need to roll back. 00154 if (mDum.mServerRegistrationHandler && !mDum.mServerRegistrationHandler->asyncProcessing()) 00155 { 00156 // Rollback changes, since rejected 00157 RegistrationPersistenceManager *database = mDum.mRegistrationPersistenceManager; 00158 database->removeAor(mAor); 00159 if (mOriginalContacts.get()) 00160 { 00161 database->addAor(mAor, *mOriginalContacts); 00162 } 00163 database->unlockRecord(mAor); 00164 } 00165 00166 SharedPtr<SipMessage> failure(new SipMessage); 00167 mDum.makeResponse(*failure, mRequest, statusCode); 00168 failure->remove(h_Contacts); 00169 mDum.send(failure); 00170 delete(this); 00171 } 00172 00173 void 00174 ServerRegistration::dispatch(const SipMessage& msg) 00175 { 00176 DebugLog( << "got a registration" ); 00177 00178 assert(msg.isRequest()); 00179 ServerRegistrationHandler* handler = mDum.mServerRegistrationHandler; 00180 RegistrationPersistenceManager *database = mDum.mRegistrationPersistenceManager; 00181 00182 if (!handler || (!handler->asyncProcessing() && !database)) 00183 { 00184 // ?bwc? This is a server error; why are we sending a 4xx? 00185 // ?jmatthewsr? Possibly because of the note in section 21.5.2 about recognizing the method, but not supporting it? 00186 DebugLog( << "No handler or DB - sending 405" ); 00187 00188 SharedPtr<SipMessage> failure(new SipMessage); 00189 mDum.makeResponse(*failure, msg, 405); 00190 mDum.send(failure); 00191 delete(this); 00192 return; 00193 } 00194 00195 mAor = msg.header(h_To).uri().getAorAsUri(msg.getSource().getType()); 00196 00197 // Checks to see whether this scheme is valid, and supported. 00198 if (!((mAor.scheme()=="sip" || mAor.scheme()=="sips") 00199 && mDum.getMasterProfile()->isSchemeSupported(mAor.scheme()))) 00200 { 00201 DebugLog( << "Bad scheme in Aor" ); 00202 00203 SharedPtr<SipMessage> failure(new SipMessage); 00204 mDum.makeResponse(*failure, msg, 400); 00205 failure->header(h_StatusLine).reason() = "Bad/unsupported scheme in To: " + mAor.scheme(); 00206 mDum.send(failure); 00207 delete(this); 00208 return; 00209 } 00210 00211 if (handler->asyncProcessing()) 00212 { 00213 mAsyncState = asyncStateWaitingForInitialContactList; 00214 handler->asyncGetContacts(getHandle(),mAor); 00216 return; 00217 } 00218 00219 processRegistration(msg); 00220 } 00221 00222 void 00223 ServerRegistration::processRegistration(const SipMessage& msg) 00224 { 00225 ServerRegistrationHandler* handler = mDum.mServerRegistrationHandler; 00226 RegistrationPersistenceManager *database = mDum.mRegistrationPersistenceManager; 00227 00228 enum {ADD, REMOVE, REFRESH} operation = REFRESH; 00229 00230 UInt32 globalExpires=3600; 00231 UInt32 returnCode=0; 00232 handler->getGlobalExpires(msg,mDum.getMasterProfile(),globalExpires,returnCode); 00233 00234 bool async = handler->asyncProcessing(); 00235 00236 if (returnCode >= 400) 00237 { 00238 SharedPtr<SipMessage> failure(new SipMessage); 00239 mDum.makeResponse(*failure, msg, returnCode); 00240 if (423 == returnCode) 00241 { 00242 failure->header(h_StatusLine).reason() = "Interval Too Brief"; 00243 failure->header(h_MinExpires).value() = globalExpires; 00244 } 00245 mDum.send(failure); 00246 delete(this); 00247 return; 00248 } 00249 00250 if (!async) 00251 { 00252 database->lockRecord(mAor); 00253 00254 mOriginalContacts = resip::SharedPtr<ContactList>(new ContactList); 00255 database->getContacts(mAor, *mOriginalContacts); 00256 } 00257 00258 // If no contacts are present in the request, this is simply a query. 00259 if (!msg.exists(h_Contacts)) 00260 { 00261 if (async) 00262 { 00263 mAsyncState = asyncStateQueryOnly; 00264 } 00265 handler->onQuery(getHandle(), msg); 00267 return; 00268 } 00269 00270 ParserContainer<NameAddr> contactList(msg.header(h_Contacts)); 00271 ParserContainer<NameAddr>::iterator i(contactList.begin()); 00272 ParserContainer<NameAddr>::iterator iEnd(contactList.end()); 00273 UInt64 now=Timer::getTimeSecs(); 00274 UInt32 expires=0; 00275 00276 for (; i != iEnd; ++i) 00277 { 00278 if (!i->isWellFormed()) 00279 { 00280 SharedPtr<SipMessage> failure(new SipMessage); 00281 mDum.makeResponse(*failure, msg, 400, "Malformed Contact"); 00282 mDum.send(failure); 00283 if (!async) 00284 { 00285 database->unlockRecord(mAor); 00286 } 00287 delete(this); 00288 return; 00289 } 00290 00291 expires = globalExpires; 00292 handler->getContactExpires(*i, mDum.getMasterProfile(), expires, returnCode); 00293 00294 // Check for "Contact: *" style deregistration 00295 if (i->isAllContacts()) 00296 { 00297 if (contactList.size() > 1 || expires != 0) 00298 { 00299 SharedPtr<SipMessage> failure(new SipMessage); 00300 mDum.makeResponse(*failure, msg, 400, "Invalid use of 'Contact: *'"); 00301 mDum.send(failure); 00302 if (!async) 00303 { 00304 database->unlockRecord(mAor); 00305 } 00306 delete(this); 00307 return; 00308 } 00309 00310 if (!async) 00311 { 00312 database->removeAor(mAor); 00313 } 00314 else 00315 { 00316 mAsyncLocalStore->removeAllContacts(); 00317 mAsyncState = asyncStateWaitingForAcceptReject; 00318 } 00319 00320 handler->onRemoveAll(getHandle(), msg); 00322 return; 00323 } 00324 00325 ContactInstanceRecord rec; 00326 rec.mContact=*i; 00327 rec.mRegExpires=(UInt64)expires+now; 00328 00329 if(i->exists(p_Instance)) 00330 { 00331 rec.mInstance=i->param(p_Instance); 00332 } 00333 00334 if(!msg.empty(h_Paths)) 00335 { 00336 rec.mSipPath=msg.header(h_Paths); 00337 } 00338 00339 rec.mLastUpdated=now; 00340 rec.mReceivedFrom=msg.getSource(); 00341 rec.mPublicAddress=Helper::getClientPublicAddress(msg); 00342 00343 bool hasFlow = tryFlow(rec,msg); 00344 00345 if(!testFlowRequirements(rec, msg, hasFlow)) 00346 { 00347 // We have rejected the request. Bail. 00348 if (!async) 00349 { 00350 database->unlockRecord(mAor); 00351 } 00352 delete(this); 00353 return; 00354 } 00355 00356 // Add ContactInstanceRecord to List 00357 mRequestContacts.push_back(rec); 00358 00359 // Check to see if this is a removal. 00360 if (expires == 0) 00361 { 00362 if (operation == REFRESH) 00363 { 00364 operation = REMOVE; 00365 } 00366 00367 if (!async) 00368 { 00369 database->removeContact(mAor, rec); 00370 } 00371 else 00372 { 00373 mAsyncLocalStore->removeContact(rec); 00374 } 00375 } 00376 else // Otherwise, it's an addition or refresh. 00377 { 00378 RegistrationPersistenceManager::update_status_t status; 00379 InfoLog(<< "Adding " << mAor << " -> " << *i); 00380 DebugLog(<< "Contact has tuple " << rec.mReceivedFrom << " and detected public address " << rec.mPublicAddress); 00381 00382 if (!async) 00383 { 00384 status = database->updateContact(mAor, rec); 00385 } 00386 else 00387 { 00388 status = mAsyncLocalStore->updateContact(rec); 00389 } 00390 00391 if (status == RegistrationPersistenceManager::CONTACT_CREATED) 00392 { 00393 operation = ADD; 00394 } 00395 } 00396 } 00397 00398 // The way this works is: 00399 // 00400 // - If no additions or removals are performed, this is a refresh 00401 // 00402 // - If at least one contact is removed and none are added, this 00403 // is a removal. 00404 // 00405 // - If at least one contact is added, this is an addition, *even* 00406 // *if* a contact was also removed. 00407 00408 //for async processing, need to wait for accept()/reject(). If accepted, the modifications made here will be 00409 //sent to the user via asyncUpdateContacts(). The user then returns a final contact list, which is then processed 00410 //and sent back in the 200. 00411 if (async) 00412 { 00413 mAsyncState = asyncStateWaitingForAcceptReject; 00414 } 00415 00416 switch (operation) 00417 { 00418 case REFRESH: 00419 handler->onRefresh(getHandle(), msg); 00421 return; 00422 00423 case REMOVE: 00424 handler->onRemove(getHandle(), msg); 00426 return; 00427 00428 case ADD: 00429 handler->onAdd(getHandle(), msg); 00431 return; 00432 00433 default: 00434 assert(0); 00435 } 00436 } 00437 00438 void 00439 ServerRegistration::dispatch(const DumTimeout& msg) 00440 { 00441 } 00442 00443 EncodeStream& 00444 ServerRegistration::dump(EncodeStream& strm) const 00445 { 00446 strm << "ServerRegistration " << mAor; 00447 return strm; 00448 } 00449 00450 bool 00451 ServerRegistration::tryFlow(ContactInstanceRecord& rec, 00452 const resip::SipMessage& msg) 00453 { 00454 // .bwc. ie. Can we assure that the connection the client is using on the 00455 // first hop can be re-used later? 00456 try 00457 { 00458 // Outbound logic 00459 if(InteropHelper::getOutboundSupported()) 00460 { 00461 resip::NameAddr& contact(rec.mContact); 00462 if(contact.exists(p_Instance) && contact.exists(p_regid)) 00463 { 00464 if(!msg.empty(h_Paths) && (msg.header(h_Paths).back().uri().exists(p_ob) || 00465 InteropHelper::getAssumeFirstHopSupportsOutboundEnabled())) 00466 { 00467 rec.mRegId=contact.param(p_regid); 00468 // Edge-proxy is directly connected to the client, and ready to 00469 // send traffic down the "connection" (TCP connection, or NAT 00470 // pinhole, or what-have-you). 00471 mDidOutbound=true; 00472 return true; 00473 } 00474 else if(msg.header(h_Vias).size() == 1) 00475 { 00476 rec.mRegId=contact.param(p_regid); 00477 // We are directly connected to the client. 00478 // .bwc. In the outbound case, we should fail if the connection 00479 // is gone. No recovery should be attempted by the server. 00480 rec.mUseFlowRouting = true; 00481 rec.mReceivedFrom.onlyUseExistingConnection=true; 00482 mDidOutbound=true; 00483 return true; 00484 } 00485 } 00486 } 00487 00488 // Record-Route flow token hack, or client NAT detect hack; use with caution 00489 if(msg.header(h_Vias).size() == 1) // client is directly connected to this server 00490 { 00491 if(InteropHelper::getRRTokenHackEnabled() || 00492 flowTokenNeededForTls(rec) || 00493 flowTokenNeededForSigcomp(rec) || 00494 (InteropHelper::getClientNATDetectionMode() != InteropHelper::ClientNATDetectionDisabled && 00495 Helper::isClientBehindNAT(msg, InteropHelper::getClientNATDetectionMode() == InteropHelper::ClientNATDetectionPrivateToPublicOnly))) 00496 { 00497 rec.mUseFlowRouting = true; 00498 rec.mReceivedFrom.onlyUseExistingConnection=false; 00499 return true; 00500 } 00501 } 00502 } 00503 catch(resip::ParseBuffer::Exception&) 00504 {} 00505 return false; 00506 } 00507 00508 bool 00509 ServerRegistration::testFlowRequirements(ContactInstanceRecord &rec, 00510 const resip::SipMessage& msg, 00511 bool hasFlow) const 00512 { 00513 const resip::NameAddr& contact(rec.mContact); 00514 00515 if(contact.exists(p_Instance) && contact.exists(p_regid)) 00516 { 00517 // Client has explicitly requested Outbound processing, which requires us 00518 // to have a flow. 00519 if(!hasFlow) 00520 { 00521 SharedPtr<SipMessage> failure(new SipMessage); 00522 mDum.makeResponse(*failure, msg, 439); 00523 mDum.send(failure); 00524 return false; 00525 } 00526 } 00527 00528 if(!hasFlow && flowTokenNeededForTls(rec)) 00529 { 00530 SharedPtr<SipMessage> failure(new SipMessage); 00531 mDum.makeResponse(*failure, msg, 400, "Trying to use TLS with an IP-address in your Contact header won't work if you don't have a flow. Consider implementing outbound, or putting an FQDN in your contact header."); 00532 mDum.send(failure); 00533 return false; 00534 } 00535 00536 if(!hasFlow && flowTokenNeededForSigcomp(rec)) 00537 { 00538 SharedPtr<SipMessage> failure(new SipMessage); 00539 mDum.makeResponse(*failure, msg, 400, "Trying to use sigcomp on a connection-oriented protocol won't work if you don't have a flow. Consider implementing outbound, or using UDP/DTLS for this case."); 00540 mDum.send(failure); 00541 return false; 00542 } 00543 00544 return true; 00545 } 00546 00547 bool 00548 ServerRegistration::flowTokenNeededForTls(const ContactInstanceRecord &rec) const 00549 { 00550 const resip::NameAddr& contact(rec.mContact); 00551 if(DnsUtil::isIpAddress(contact.uri().host())) 00552 { 00553 // IP address in host-part. 00554 if(contact.uri().scheme()=="sips") 00555 { 00556 // sips: and IP-address in contact. This will probably not work anyway. 00557 return true; 00558 } 00559 00560 if(contact.uri().exists(p_transport)) 00561 { 00562 TransportType type = Tuple::toTransport(contact.uri().param(p_transport)); 00563 if(type==TLS || type == DTLS) 00564 { 00565 // secure transport and IP-address. Almost certainly won't work, but 00566 // we'll try anyway. 00567 return true; 00568 } 00569 } 00570 } 00571 return false; 00572 } 00573 00574 bool 00575 ServerRegistration::flowTokenNeededForSigcomp(const ContactInstanceRecord &rec) const 00576 { 00577 const resip::NameAddr& contact(rec.mContact); 00578 00579 if(contact.uri().exists(p_sigcompId)) 00580 { 00581 if(contact.uri().exists(p_transport)) 00582 { 00583 TransportType type = Tuple::toTransport(contact.uri().param(p_transport)); 00584 if(type == TLS || type == TCP) 00585 { 00586 // Client is using sigcomp on the first hop using a connection- 00587 // oriented transport. For this to work, that connection has to be 00588 // reused for all traffic. 00589 return true; 00590 } 00591 } 00592 else 00593 { 00594 // ?bwc? Client is using sigcomp, but we're not sure whether this is 00595 // over a connection-oriented transport or not. 00596 DebugLog(<< "Client is using sigcomp, but we're not sure whether this " 00597 "is over a connection-oriented transport or not, because " 00598 "the contact doesn't have a transport param in it. It is " 00599 "possible this will work though, so we'll let it proceed." 00600 ); 00601 } 00602 } 00603 return false; 00604 } 00605 00606 00607 void 00608 ServerRegistration::asyncProcessFinalOkMsg(SipMessage &msg, ContactPtrList &contacts) 00609 { 00610 if (contacts.size() > 0) 00611 { 00612 ContactPtrList::iterator it(contacts.begin()); 00613 ContactPtrList::iterator itEnd(contacts.end()); 00614 00615 std::auto_ptr<ContactPtrList> expired; 00616 00617 UInt64 now=Timer::getTimeSecs(); 00618 00619 for (;it != itEnd;++it) 00620 { 00621 resip::SharedPtr<ContactInstanceRecord> rec(*it); 00622 00623 if (!rec) 00624 { 00625 assert(0); 00626 continue; 00627 } 00628 00629 if (rec->mRegExpires <= now) 00630 { 00631 if (!expired.get()) 00632 { 00633 expired = std::auto_ptr<ContactPtrList>(new ContactPtrList()); 00634 } 00635 expired->push_back(rec); 00636 continue; 00637 } 00638 00639 rec->mContact.param(p_expires) = UInt32(rec->mRegExpires - now); 00640 msg.header(h_Contacts).push_back(rec->mContact); 00641 } 00642 00643 if (expired.get() && expired->size() > 0) 00644 { 00645 mDum.mServerRegistrationHandler->asyncRemoveExpired(getHandle(),mAor,expired); 00647 return; 00648 } 00649 } 00650 } 00651 00652 void 00653 ServerRegistration::processFinalOkMsg(SipMessage &msg, ContactList &contacts) 00654 { 00655 //build the 200Ok and remove any expired entries. 00656 //the non-asynchronous behavior is to call the database directly, the async behavior is to build a 00657 //list of all expired entries and send it to the handler. 00658 if (contacts.size() > 0) 00659 { 00660 ContactList::iterator it(contacts.begin()); 00661 ContactList::iterator itEnd(contacts.end()); 00662 00663 RegistrationPersistenceManager *database = mDum.mRegistrationPersistenceManager; 00664 UInt64 now=Timer::getTimeSecs(); 00665 00666 for (;it != itEnd;++it) 00667 { 00668 if (it->mRegExpires <= now) 00669 { 00670 database->removeContact(mAor,*it); 00671 continue; 00672 } 00673 it->mContact.param(p_expires) = UInt32(it->mRegExpires - now); 00674 msg.header(h_Contacts).push_back(it->mContact); 00675 } 00676 } 00677 } 00678 00679 bool 00680 ServerRegistration::asyncProvideContacts(std::auto_ptr<resip::ContactPtrList> contacts) 00681 { 00682 switch (mAsyncState) 00683 { 00684 case asyncStateWaitingForInitialContactList: 00685 { 00686 assert(mAsyncLocalStore.get() == 0); 00687 mAsyncLocalStore = resip::SharedPtr<AsyncLocalStore>(new AsyncLocalStore(contacts)); 00688 mAsyncState = asyncStateProcessingRegistration; 00689 processRegistration(mRequest); 00690 break; 00691 } 00692 case asyncStateWaitingForAcceptReject: 00693 { 00694 assert(0); //need to call accept() or reject(), wait for asyncUpdateContacts(), then call this function. 00695 return false; 00696 } 00697 case asyncStateAcceptedWaitingForFinalContactList: 00698 { 00699 mAsyncState = asyncStateProvidedFinalContacts; 00700 asyncProcessFinalContacts(contacts); 00701 break; 00702 } 00703 default: 00704 { 00705 assert(0); 00706 return false; 00707 } 00708 } 00709 00710 return true; 00711 } 00712 00713 void 00714 ServerRegistration::asyncProcessFinalContacts(std::auto_ptr<resip::ContactPtrList> contacts) 00715 { 00716 if (contacts.get()) 00717 { 00718 if (!mAsyncOkMsg.get()) 00719 { 00720 assert(0); 00721 } 00722 else 00723 { 00724 asyncProcessFinalOkMsg(*mAsyncOkMsg,*contacts); 00725 } 00726 } 00727 00728 mAsyncState = asyncStateNone; 00729 mDum.send(mAsyncOkMsg); 00730 mAsyncOkMsg.reset(); 00731 delete(this); 00732 } 00733 00734 void 00735 ServerRegistration::AsyncLocalStore::create(std::auto_ptr<ContactPtrList> originalContacts) 00736 { 00737 mModifiedContacts = originalContacts; 00738 mLog = std::auto_ptr<ContactRecordTransactionLog>(new ContactRecordTransactionLog()); 00739 } 00740 00741 void 00742 ServerRegistration::AsyncLocalStore::destroy(void) 00743 { 00744 mModifiedContacts.reset(); 00745 mLog.reset(); 00746 } 00747 00748 RegistrationPersistenceManager::update_status_t 00749 ServerRegistration::AsyncLocalStore::updateContact(const ContactInstanceRecord &rec) 00750 { 00751 if (!mModifiedContacts.get() || !mLog.get()) 00752 { 00753 assert(0); 00754 return RegistrationPersistenceManager::CONTACT_UPDATED; 00755 } 00756 00757 ContactPtrList::iterator it(mModifiedContacts->begin()); 00758 ContactPtrList::iterator itEnd(mModifiedContacts->end()); 00759 00760 resip::SharedPtr<ContactRecordTransaction> logEntry; 00761 00762 // See if the contact is already present. We use URI matching rules here. 00763 for (; it != itEnd; ++it) 00764 { 00765 if ((*it) && **it == rec) 00766 { 00767 **it = rec; 00768 00769 logEntry = resip::SharedPtr<ContactRecordTransaction>(new ContactRecordTransaction(ContactRecordTransaction::update,*it)); 00770 mLog->push_back(logEntry); 00771 00772 return RegistrationPersistenceManager::CONTACT_UPDATED; 00773 } 00774 } 00775 00776 // This is a new contact, so we add it to the list. 00777 resip::SharedPtr<ContactInstanceRecord> newRec(new ContactInstanceRecord(rec)); 00778 00779 logEntry = resip::SharedPtr<ContactRecordTransaction>(new ContactRecordTransaction(ContactRecordTransaction::create,newRec)); 00780 mLog->push_back(logEntry); 00781 00782 mModifiedContacts->push_back(newRec); 00783 00784 return RegistrationPersistenceManager::CONTACT_CREATED; 00785 } 00786 00787 void 00788 ServerRegistration::AsyncLocalStore::removeContact(const ContactInstanceRecord &rec) 00789 { 00790 if (!mModifiedContacts.get() || !mLog.get()) 00791 { 00792 assert(0); 00793 return; 00794 } 00795 00796 ContactPtrList::iterator it(mModifiedContacts->begin()); 00797 ContactPtrList::iterator itEnd(mModifiedContacts->end()); 00798 00799 // See if the contact is present. We use URI matching rules here. 00800 for (; it != itEnd; ++it) 00801 { 00802 if ((*it) && **it == rec) 00803 { 00804 resip::SharedPtr<ContactRecordTransaction> 00805 logEntry(resip::SharedPtr<ContactRecordTransaction> 00806 (new ContactRecordTransaction(ContactRecordTransaction::remove,*it))); 00807 00808 mLog->push_back(logEntry); 00809 00810 mModifiedContacts->erase(it); 00811 return; 00812 } 00813 } 00814 } 00815 00816 void 00817 ServerRegistration::AsyncLocalStore::removeAllContacts(void) 00818 { 00819 if (!mModifiedContacts.get() || !mLog.get()) 00820 { 00821 return; 00822 } 00823 00824 resip::SharedPtr<ContactInstanceRecord> recNull; 00825 00826 resip::SharedPtr<ContactRecordTransaction> 00827 logEntry(resip::SharedPtr<ContactRecordTransaction>(new ContactRecordTransaction(ContactRecordTransaction::removeAll,recNull))); 00828 00829 mLog->push_back(logEntry); 00830 00831 mModifiedContacts->clear(); 00832 } 00833 00834 00835 /* ==================================================================== 00836 * The Vovida Software License, Version 1.0 00837 * 00838 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00839 * 00840 * Redistribution and use in source and binary forms, with or without 00841 * modification, are permitted provided that the following conditions 00842 * are met: 00843 * 00844 * 1. Redistributions of source code must retain the above copyright 00845 * notice, this list of conditions and the following disclaimer. 00846 * 00847 * 2. Redistributions in binary form must reproduce the above copyright 00848 * notice, this list of conditions and the following disclaimer in 00849 * the documentation and/or other materials provided with the 00850 00851 * distribution. 00852 * 00853 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00854 * and "Vovida Open Communication Application Library (VOCAL)" must 00855 * not be used to endorse or promote products derived from this 00856 * software without prior written permission. For written 00857 * permission, please contact vocal@vovida.org. 00858 * 00859 * 4. Products derived from this software may not be called "VOCAL", nor 00860 * may "VOCAL" appear in their name, without prior written 00861 * permission of Vovida Networks, Inc. 00862 * 00863 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00864 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00865 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00866 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00867 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00868 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00869 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00870 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00871 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00872 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00873 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00874 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00875 * DAMAGE. 00876 * 00877 * ==================================================================== 00878 * 00879 * This software consists of voluntary contributions made by Vovida 00880 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00881 * Inc. For more information on Vovida Networks, Inc., please see 00882 * <http://www.vovida.org/>. 00883 * 00884 */
1.7.5.1