|
reSIProcate/DialogUsageManager
9694
|
#include <ServerRegistration.hxx>


Classes | |
| class | AsyncLocalStore |
| Local datastore used to aggregate all changes to the current contact list when using the asynchronous logic. More... | |
Public Member Functions | |
| ServerRegistrationHandle | getHandle () |
| void | accept (SipMessage &ok) |
| Accept a SIP registration with a specific response. | |
| void | accept (int statusCode=200) |
| Accept a SIP registration. | |
| void | reject (int statusCode) |
| Reject a SIP registration. | |
| virtual void | end () |
| virtual void | dispatch (const SipMessage &msg) |
| virtual void | dispatch (const DumTimeout &timer) |
| virtual EncodeStream & | dump (EncodeStream &strm) const |
| bool | asyncProvideContacts (std::auto_ptr< resip::ContactPtrList > contacts) |
| Used when useAsyncProcessing() is true. | |
| resip::SharedPtr< ContactList > | getOriginalContacts () |
| const ContactList & | getRequestContacts () |
Protected Member Functions | |
| virtual | ~ServerRegistration () |
Private Types | |
| enum | AsyncState { asyncStateNone, asyncStateWaitingForInitialContactList, asyncStateProcessingRegistration, asyncStateWaitingForAcceptReject, asyncStateAcceptedWaitingForFinalContactList, asyncStateProvidedFinalContacts, asyncStateQueryOnly } |
| States are used to keep track of asynchronous requests made to the database. More... | |
| typedef enum resip::ServerRegistration::AsyncState | AsyncState |
| States are used to keep track of asynchronous requests made to the database. | |
Private Member Functions | |
| ServerRegistration (DialogUsageManager &dum, DialogSet &dialogSet, const SipMessage &request) | |
| bool | tryFlow (ContactInstanceRecord &rec, const resip::SipMessage &msg) |
| bool | flowTokenNeededForTls (const ContactInstanceRecord &rec) const |
| bool | flowTokenNeededForSigcomp (const ContactInstanceRecord &rec) const |
| bool | testFlowRequirements (ContactInstanceRecord &rec, const resip::SipMessage &msg, bool hasFlow) const |
| ServerRegistration (const ServerRegistration &) | |
| ServerRegistration & | operator= (const ServerRegistration &) |
| void | processRegistration (const SipMessage &msg) |
| Look at the contacts provided by the incoming REGISTER. | |
| void | asyncProcessFinalOkMsg (SipMessage &msg, ContactPtrList &contacts) |
| void | processFinalOkMsg (SipMessage &msg, ContactList &contacts) |
| Add contacs to msg, adding expires param. | |
| void | asyncProcessFinalContacts (std::auto_ptr< resip::ContactPtrList > contacts) |
| After the user calls accept(), ServerRegistration will apply the local contact list and wait for a final contact list. | |
Private Attributes | |
| SipMessage | mRequest |
| Uri | mAor |
| resip::SharedPtr< ContactList > | mOriginalContacts |
| ContactList | mRequestContacts |
| bool | mDidOutbound |
| AsyncState | mAsyncState |
| resip::SharedPtr< AsyncLocalStore > | mAsyncLocalStore |
| resip::SharedPtr< SipMessage > | mAsyncOkMsg |
| Message stored during accept() call when waiting for final contact list from database. | |
Friends | |
| class | DialogSet |
Definition at line 11 of file ServerRegistration.hxx.
typedef enum resip::ServerRegistration::AsyncState resip::ServerRegistration::AsyncState [private] |
States are used to keep track of asynchronous requests made to the database.
Typical activity & state progression for a successful registration (onQuery & reject() are slightly different):
DUM ServerRegistration RegistrationHandler _____________________________________________________________________________________________________
1) dispatch()/asyncStateNone---> 2) asyncGetContacts()/asyncStateWaitingForInitialContactList---> ====================================================================================================== 3) <---asyncProvideContacts()/asyncStateProcessingRegistration 4) processRegistration() 5) (onRefresh()|onRemove()|onAdd()|onRemoveAll()|onQuery)/asyncStateWaitingForAcceptReject---> ====================================================================================================== 6) <---accept() 7) asyncUpdateContacts/asyncStateAcceptedWaitingForFinalContactList---> ====================================================================================================== 8) <---asyncProvideContacts()/asyncStateProvidedFinalContacts 9) asyncProcessFinalContacts()/asyncStateNone 10) <---send(200Ok) ______________________________________________________________________________________________________
onQuery processing is similar, except it immediately sends the 200Ok after handling the accept().
ServerRegistration::reject() does not require roll-back and the error is immediately sent back to DUM.
It is possible to call ServerRegistration::reject() after calling accept() (DB failure, app failure, etc)
enum resip::ServerRegistration::AsyncState [private] |
States are used to keep track of asynchronous requests made to the database.
Typical activity & state progression for a successful registration (onQuery & reject() are slightly different):
DUM ServerRegistration RegistrationHandler _____________________________________________________________________________________________________
1) dispatch()/asyncStateNone---> 2) asyncGetContacts()/asyncStateWaitingForInitialContactList---> ====================================================================================================== 3) <---asyncProvideContacts()/asyncStateProcessingRegistration 4) processRegistration() 5) (onRefresh()|onRemove()|onAdd()|onRemoveAll()|onQuery)/asyncStateWaitingForAcceptReject---> ====================================================================================================== 6) <---accept() 7) asyncUpdateContacts/asyncStateAcceptedWaitingForFinalContactList---> ====================================================================================================== 8) <---asyncProvideContacts()/asyncStateProvidedFinalContacts 9) asyncProcessFinalContacts()/asyncStateNone 10) <---send(200Ok) ______________________________________________________________________________________________________
onQuery processing is similar, except it immediately sends the 200Ok after handling the accept().
ServerRegistration::reject() does not require roll-back and the error is immediately sent back to DUM.
It is possible to call ServerRegistration::reject() after calling accept() (DB failure, app failure, etc)
| asyncStateNone | |
| asyncStateWaitingForInitialContactList |
Sent an asynchronous request to get the current contact list from the DB. |
| asyncStateProcessingRegistration |
received the initial contact list, processing the current REGISTER request and updating the contact list. |
| asyncStateWaitingForAcceptReject |
RegistrationHandler called, waiting for accept() or reject() from user. |
| asyncStateAcceptedWaitingForFinalContactList |
asyncUpdateContacts() has been called, waiting for final list. |
| asyncStateProvidedFinalContacts |
After receiving the final contact list; process the accepted register and send response. |
| asyncStateQueryOnly |
The REGISTER is a query, so just send back the current list in accept(). |
Definition at line 107 of file ServerRegistration.hxx.
| ServerRegistration::~ServerRegistration | ( | ) | [protected, virtual] |
Definition at line 33 of file ServerRegistration.cxx.
References resip::NonDialogUsage::mDialogSet, and resip::DialogSet::mServerRegistration.
{
mDialogSet.mServerRegistration = 0;
}
| ServerRegistration::ServerRegistration | ( | DialogUsageManager & | dum, |
| DialogSet & | dialogSet, | ||
| const SipMessage & | request | ||
| ) | [private] |
Definition at line 26 of file ServerRegistration.cxx.
: NonDialogUsage(dum, dialogSet), mRequest(request), mDidOutbound(false), mAsyncState(asyncStateNone) {}
| resip::ServerRegistration::ServerRegistration | ( | const ServerRegistration & | ) | [private] |
| void ServerRegistration::accept | ( | SipMessage & | ok | ) |
Accept a SIP registration with a specific response.
Any contacts in this message will be deleted and replaced with the list created during REGISTER processing.
!Warning! After calling this function from a ServerRegistrationHandle, do not access the handle as this function may delete this object. Use ServerRegistrationHandle::isValidHandle() to test if it's deleted.
WARN! Must not access this object beyond this point. The client my call reject() or accept(), deleting this object. Also, watch out for local objects that are still in scope and access this object on destruction.
Definition at line 45 of file ServerRegistration.cxx.
References asyncProcessFinalOkMsg(), resip::ServerRegistrationHandler::asyncProcessing(), asyncStateAcceptedWaitingForFinalContactList, asyncStateQueryOnly, resip::ServerRegistrationHandler::asyncUpdateContacts(), resip::SipMessage::clone(), resip::SipStack::enableFlowTimer(), resip::SharedPtr< T >::get(), resip::RegistrationPersistenceManager::getContacts(), resip::InteropHelper::getFlowTimerSeconds(), getHandle(), resip::DialogUsageManager::getSipStack(), resip::SipMessage::getSource(), resip::SipMessage::header(), InfoLog, mAor, mAsyncLocalStore, mAsyncOkMsg, mAsyncState, mDidOutbound, resip::BaseUsage::mDum, resip::DialogUsageManager::mRegistrationPersistenceManager, mRequest, resip::DialogUsageManager::mServerRegistrationHandler, outbound, processFinalOkMsg(), resip::SipMessage::remove(), resip::DialogUsageManager::send(), and resip::RegistrationPersistenceManager::unlockRecord().
Referenced by accept().
{
ok.remove(h_Contacts);
InfoLog( << "accepted a registration " << mAor );
if (mDidOutbound)
{
ok.header(h_Requires).push_back(outbound);
if(InteropHelper::getFlowTimerSeconds() > 0)
{
ok.header(h_FlowTimer).value() = InteropHelper::getFlowTimerSeconds();
mDum.getSipStack().enableFlowTimer(mRequest.getSource());
}
}
if (!mDum.mServerRegistrationHandler->asyncProcessing())
{
// Add all registered contacts to the message.
RegistrationPersistenceManager *database = mDum.mRegistrationPersistenceManager;
ContactList contacts;
database->getContacts(mAor, contacts);
//removes expired entries from the ok msg as well as calls the database to remove expired contacts.
processFinalOkMsg(ok,contacts);
database->unlockRecord(mAor);
SharedPtr<SipMessage> msg(static_cast<SipMessage*>(ok.clone()));
mDum.send(msg);
delete(this);
}
else
{
if (mAsyncState == asyncStateQueryOnly)
{
if (!mAsyncLocalStore.get())
{
assert(0);
}
else
{
std::auto_ptr<ContactRecordTransactionLog> log;
std::auto_ptr<ContactPtrList> contacts;
mAsyncLocalStore->releaseLog(log,contacts);
if (contacts.get())
{
asyncProcessFinalOkMsg(ok,*contacts);
}
}
SharedPtr<SipMessage> msg(static_cast<SipMessage*>(ok.clone()));
mDum.send(msg);
delete(this);
}
else
{
if (!mAsyncLocalStore.get())
{
assert(0);
return;
}
//This register was accepted, but still need to apply the changes made by this register and then
//receive a final contact list before sending the 200.
mAsyncState = asyncStateAcceptedWaitingForFinalContactList;
std::auto_ptr<ContactRecordTransactionLog> log;
std::auto_ptr<ContactPtrList> modifiedContacts;
mAsyncLocalStore->releaseLog(log,modifiedContacts);
mAsyncOkMsg = SharedPtr<SipMessage>(static_cast<SipMessage*>(ok.clone()));
mDum.mServerRegistrationHandler->asyncUpdateContacts(getHandle(),mAor,modifiedContacts,log);
return;
}
}
}

| void ServerRegistration::accept | ( | int | statusCode = 200 | ) |
Accept a SIP registration.
!Warning! After calling this function from a ServerRegistrationHandle, do not access the handle as this function may delete this object. Use ServerRegistrationHandle::isValidHandle() to test if it's deleted.
Definition at line 128 of file ServerRegistration.cxx.
References accept(), resip::SipMessage::empty(), resip::SipMessage::header(), resip::DialogUsageManager::makeResponse(), resip::BaseUsage::mDum, mRequest, and resip::Symbols::Path.
{
SipMessage success;
mDum.makeResponse(success, mRequest, statusCode);
// .bwc. Copy Path headers if present, indicate Path support
// ?bwc? If path headers are present, but client indicates no path support,
// RFC 3327 says it is a matter of policy of whether to accept the
// registration or not. What should we do here? Is it worth it to make this
// configurable?
if(!mRequest.empty(h_Paths))
{
success.header(h_Paths)=mRequest.header(h_Paths);
success.header(h_Supporteds).push_back(Token(Symbols::Path));
}
accept(success);
}

| void ServerRegistration::asyncProcessFinalContacts | ( | std::auto_ptr< resip::ContactPtrList > | contacts | ) | [private] |
After the user calls accept(), ServerRegistration will apply the local contact list and wait for a final contact list.
Once the final list is received via asyncProvideContacts(), this function finishes the REGISTER processing.
Definition at line 714 of file ServerRegistration.cxx.
References asyncProcessFinalOkMsg(), asyncStateNone, resip::SharedPtr< T >::get(), mAsyncOkMsg, mAsyncState, resip::BaseUsage::mDum, resip::SharedPtr< T >::reset(), and resip::DialogUsageManager::send().
Referenced by asyncProvideContacts().
{
if (contacts.get())
{
if (!mAsyncOkMsg.get())
{
assert(0);
}
else
{
asyncProcessFinalOkMsg(*mAsyncOkMsg,*contacts);
}
}
mAsyncState = asyncStateNone;
mDum.send(mAsyncOkMsg);
mAsyncOkMsg.reset();
delete(this);
}

| void ServerRegistration::asyncProcessFinalOkMsg | ( | SipMessage & | msg, |
| ContactPtrList & | contacts | ||
| ) | [private] |
WARN! Must not access this object beyond this point. The client my call reject() or accept(), deleting this object. Also, watch out for local objects that are still in scope and access this object on destruction.
Definition at line 608 of file ServerRegistration.cxx.
References resip::ServerRegistrationHandler::asyncRemoveExpired(), expired(), getHandle(), resip::Timer::getTimeSecs(), resip::SipMessage::header(), mAor, resip::BaseUsage::mDum, and resip::DialogUsageManager::mServerRegistrationHandler.
Referenced by accept(), and asyncProcessFinalContacts().
{
if (contacts.size() > 0)
{
ContactPtrList::iterator it(contacts.begin());
ContactPtrList::iterator itEnd(contacts.end());
std::auto_ptr<ContactPtrList> expired;
UInt64 now=Timer::getTimeSecs();
for (;it != itEnd;++it)
{
resip::SharedPtr<ContactInstanceRecord> rec(*it);
if (!rec)
{
assert(0);
continue;
}
if (rec->mRegExpires <= now)
{
if (!expired.get())
{
expired = std::auto_ptr<ContactPtrList>(new ContactPtrList());
}
expired->push_back(rec);
continue;
}
rec->mContact.param(p_expires) = UInt32(rec->mRegExpires - now);
msg.header(h_Contacts).push_back(rec->mContact);
}
if (expired.get() && expired->size() > 0)
{
mDum.mServerRegistrationHandler->asyncRemoveExpired(getHandle(),mAor,expired);
return;
}
}
}

| bool ServerRegistration::asyncProvideContacts | ( | std::auto_ptr< resip::ContactPtrList > | contacts | ) |
Used when useAsyncProcessing() is true.
Provide the current set of contacts for this registration for processing. This is required during initial registration processing to provide a local copy of the registered contacts, which are then updated by the registration processing. At the end of the registration processing this function must provide a final list of contacts after any user-defined manipulation.
!CAUTION! This function must be called from the DUM thread.
Definition at line 680 of file ServerRegistration.cxx.
References asyncProcessFinalContacts(), asyncStateAcceptedWaitingForFinalContactList, asyncStateProcessingRegistration, asyncStateProvidedFinalContacts, asyncStateWaitingForAcceptReject, asyncStateWaitingForInitialContactList, resip::SharedPtr< T >::get(), mAsyncLocalStore, mAsyncState, mRequest, and processRegistration().
{
switch (mAsyncState)
{
case asyncStateWaitingForInitialContactList:
{
assert(mAsyncLocalStore.get() == 0);
mAsyncLocalStore = resip::SharedPtr<AsyncLocalStore>(new AsyncLocalStore(contacts));
mAsyncState = asyncStateProcessingRegistration;
processRegistration(mRequest);
break;
}
case asyncStateWaitingForAcceptReject:
{
assert(0); //need to call accept() or reject(), wait for asyncUpdateContacts(), then call this function.
return false;
}
case asyncStateAcceptedWaitingForFinalContactList:
{
mAsyncState = asyncStateProvidedFinalContacts;
asyncProcessFinalContacts(contacts);
break;
}
default:
{
assert(0);
return false;
}
}
return true;
}

| void ServerRegistration::dispatch | ( | const SipMessage & | msg | ) | [virtual] |
WARN! Must not access this object beyond this point. The client my call reject() or accept(), deleting this object. Also, watch out for local objects that are still in scope and access this object on destruction.
Implements resip::BaseUsage.
Definition at line 174 of file ServerRegistration.cxx.
References asyncStateWaitingForInitialContactList, DebugLog, resip::Uri::getAorAsUri(), getHandle(), resip::DialogUsageManager::getMasterProfile(), resip::SipMessage::getSource(), resip::Tuple::getType(), h_StatusLine, resip::SipMessage::header(), resip::SipMessage::isRequest(), resip::DialogUsageManager::makeResponse(), mAor, mAsyncState, resip::BaseUsage::mDum, resip::DialogUsageManager::mRegistrationPersistenceManager, resip::DialogUsageManager::mServerRegistrationHandler, processRegistration(), resip::Uri::scheme(), resip::DialogUsageManager::send(), and resip::RequestLine::uri().
Referenced by resip::DialogSet::dispatch().
{
DebugLog( << "got a registration" );
assert(msg.isRequest());
ServerRegistrationHandler* handler = mDum.mServerRegistrationHandler;
RegistrationPersistenceManager *database = mDum.mRegistrationPersistenceManager;
if (!handler || (!handler->asyncProcessing() && !database))
{
// ?bwc? This is a server error; why are we sending a 4xx?
// ?jmatthewsr? Possibly because of the note in section 21.5.2 about recognizing the method, but not supporting it?
DebugLog( << "No handler or DB - sending 405" );
SharedPtr<SipMessage> failure(new SipMessage);
mDum.makeResponse(*failure, msg, 405);
mDum.send(failure);
delete(this);
return;
}
mAor = msg.header(h_To).uri().getAorAsUri(msg.getSource().getType());
// Checks to see whether this scheme is valid, and supported.
if (!((mAor.scheme()=="sip" || mAor.scheme()=="sips")
&& mDum.getMasterProfile()->isSchemeSupported(mAor.scheme())))
{
DebugLog( << "Bad scheme in Aor" );
SharedPtr<SipMessage> failure(new SipMessage);
mDum.makeResponse(*failure, msg, 400);
failure->header(h_StatusLine).reason() = "Bad/unsupported scheme in To: " + mAor.scheme();
mDum.send(failure);
delete(this);
return;
}
if (handler->asyncProcessing())
{
mAsyncState = asyncStateWaitingForInitialContactList;
handler->asyncGetContacts(getHandle(),mAor);
return;
}
processRegistration(msg);
}

| void ServerRegistration::dispatch | ( | const DumTimeout & | timer | ) | [virtual] |
| EncodeStream & ServerRegistration::dump | ( | EncodeStream & | strm | ) | const [virtual] |
Implements resip::BaseUsage.
Definition at line 444 of file ServerRegistration.cxx.
References mAor.
{
strm << "ServerRegistration " << mAor;
return strm;
}
| void ServerRegistration::end | ( | ) | [virtual] |
| bool ServerRegistration::flowTokenNeededForSigcomp | ( | const ContactInstanceRecord & | rec | ) | const [private] |
Definition at line 575 of file ServerRegistration.cxx.
References DebugLog, resip::Uri::exists(), resip::ContactInstanceRecord::mContact, resip::ParserCategory::param(), resip::TCP, resip::TLS, resip::Tuple::toTransport(), type, and resip::NameAddr::uri().
Referenced by testFlowRequirements(), and tryFlow().
{
const resip::NameAddr& contact(rec.mContact);
if(contact.uri().exists(p_sigcompId))
{
if(contact.uri().exists(p_transport))
{
TransportType type = Tuple::toTransport(contact.uri().param(p_transport));
if(type == TLS || type == TCP)
{
// Client is using sigcomp on the first hop using a connection-
// oriented transport. For this to work, that connection has to be
// reused for all traffic.
return true;
}
}
else
{
// ?bwc? Client is using sigcomp, but we're not sure whether this is
// over a connection-oriented transport or not.
DebugLog(<< "Client is using sigcomp, but we're not sure whether this "
"is over a connection-oriented transport or not, because "
"the contact doesn't have a transport param in it. It is "
"possible this will work though, so we'll let it proceed."
);
}
}
return false;
}

| bool ServerRegistration::flowTokenNeededForTls | ( | const ContactInstanceRecord & | rec | ) | const [private] |
Definition at line 548 of file ServerRegistration.cxx.
References resip::DTLS, resip::Uri::exists(), resip::Uri::host(), resip::DnsUtil::isIpAddress(), resip::ContactInstanceRecord::mContact, resip::ParserCategory::param(), resip::Uri::scheme(), resip::TLS, resip::Tuple::toTransport(), type, and resip::NameAddr::uri().
Referenced by testFlowRequirements(), and tryFlow().
{
const resip::NameAddr& contact(rec.mContact);
if(DnsUtil::isIpAddress(contact.uri().host()))
{
// IP address in host-part.
if(contact.uri().scheme()=="sips")
{
// sips: and IP-address in contact. This will probably not work anyway.
return true;
}
if(contact.uri().exists(p_transport))
{
TransportType type = Tuple::toTransport(contact.uri().param(p_transport));
if(type==TLS || type == DTLS)
{
// secure transport and IP-address. Almost certainly won't work, but
// we'll try anyway.
return true;
}
}
}
return false;
}

| ServerRegistrationHandle ServerRegistration::getHandle | ( | ) |
Definition at line 21 of file ServerRegistration.cxx.
References resip::BaseUsage::getBaseHandle(), and resip::BaseUsage::mDum.
Referenced by accept(), asyncProcessFinalOkMsg(), dispatch(), resip::DialogSet::getServerRegistration(), and processRegistration().
{
return ServerRegistrationHandle(mDum, getBaseHandle().getId());
}

| resip::SharedPtr<ContactList> resip::ServerRegistration::getOriginalContacts | ( | ) | [inline] |
Definition at line 52 of file ServerRegistration.hxx.
References mOriginalContacts.
{ return mOriginalContacts; } // WARNING - use this only if async mode is not used
| const ContactList& resip::ServerRegistration::getRequestContacts | ( | ) | [inline] |
Definition at line 53 of file ServerRegistration.hxx.
References mRequestContacts.
{ return mRequestContacts; }
| ServerRegistration& resip::ServerRegistration::operator= | ( | const ServerRegistration & | ) | [private] |
| void ServerRegistration::processFinalOkMsg | ( | SipMessage & | msg, |
| ContactList & | contacts | ||
| ) | [private] |
Add contacs to msg, adding expires param.
Also removes expired entries from contacts and calls the appropriate DB functions to remove them.
Definition at line 653 of file ServerRegistration.cxx.
References resip::Timer::getTimeSecs(), resip::SipMessage::header(), mAor, resip::BaseUsage::mDum, and resip::DialogUsageManager::mRegistrationPersistenceManager.
Referenced by accept().
{
//build the 200Ok and remove any expired entries.
//the non-asynchronous behavior is to call the database directly, the async behavior is to build a
//list of all expired entries and send it to the handler.
if (contacts.size() > 0)
{
ContactList::iterator it(contacts.begin());
ContactList::iterator itEnd(contacts.end());
RegistrationPersistenceManager *database = mDum.mRegistrationPersistenceManager;
UInt64 now=Timer::getTimeSecs();
for (;it != itEnd;++it)
{
if (it->mRegExpires <= now)
{
database->removeContact(mAor,*it);
continue;
}
it->mContact.param(p_expires) = UInt32(it->mRegExpires - now);
msg.header(h_Contacts).push_back(it->mContact);
}
}
}

| void ServerRegistration::processRegistration | ( | const SipMessage & | msg | ) | [private] |
Look at the contacts provided by the incoming REGISTER.
WARN! Must not access this object beyond this point. The client my call reject() or accept(), deleting this object. Also, watch out for local objects that are still in scope and access this object on destruction.
WARN! Must not access this object beyond this point. The client my call reject() or accept(), deleting this object. Also, watch out for local objects that are still in scope and access this object on destruction.
WARN! Must not access this object beyond this point. The client my call reject() or accept(), deleting this object. Also, watch out for local objects that are still in scope and access this object on destruction.
WARN! Must not access this object beyond this point. The client my call reject() or accept(), deleting this object. Also, watch out for local objects that are still in scope and access this object on destruction.
WARN! Must not access this object beyond this point. The client my call reject() or accept(), deleting this object. Also, watch out for local objects that are still in scope and access this object on destruction.
Definition at line 223 of file ServerRegistration.cxx.
References resip::ServerRegistrationHandler::asyncProcessing(), asyncStateQueryOnly, asyncStateWaitingForAcceptReject, resip::RegistrationPersistenceManager::CONTACT_CREATED, DebugLog, resip::SipMessage::empty(), resip::SipMessage::exists(), resip::Helper::getClientPublicAddress(), resip::ServerRegistrationHandler::getContactExpires(), resip::RegistrationPersistenceManager::getContacts(), resip::ServerRegistrationHandler::getGlobalExpires(), getHandle(), resip::DialogUsageManager::getMasterProfile(), resip::SipMessage::getSource(), resip::Timer::getTimeSecs(), h_StatusLine, resip::SipMessage::header(), InfoLog, resip::RegistrationPersistenceManager::lockRecord(), resip::DialogUsageManager::makeResponse(), mAor, mAsyncLocalStore, mAsyncState, resip::ContactInstanceRecord::mContact, resip::BaseUsage::mDum, resip::ContactInstanceRecord::mInstance, resip::ContactInstanceRecord::mLastUpdated, mOriginalContacts, resip::ContactInstanceRecord::mPublicAddress, resip::ContactInstanceRecord::mReceivedFrom, resip::ContactInstanceRecord::mRegExpires, resip::DialogUsageManager::mRegistrationPersistenceManager, mRequestContacts, resip::DialogUsageManager::mServerRegistrationHandler, resip::ContactInstanceRecord::mSipPath, resip::ServerRegistrationHandler::onAdd(), resip::ServerRegistrationHandler::onQuery(), resip::ServerRegistrationHandler::onRefresh(), resip::ServerRegistrationHandler::onRemove(), resip::ServerRegistrationHandler::onRemoveAll(), resip::RegistrationPersistenceManager::removeAor(), resip::RegistrationPersistenceManager::removeContact(), resip::DialogUsageManager::send(), testFlowRequirements(), tryFlow(), resip::RegistrationPersistenceManager::unlockRecord(), and resip::RegistrationPersistenceManager::updateContact().
Referenced by asyncProvideContacts(), and dispatch().
{
ServerRegistrationHandler* handler = mDum.mServerRegistrationHandler;
RegistrationPersistenceManager *database = mDum.mRegistrationPersistenceManager;
enum {ADD, REMOVE, REFRESH} operation = REFRESH;
UInt32 globalExpires=3600;
UInt32 returnCode=0;
handler->getGlobalExpires(msg,mDum.getMasterProfile(),globalExpires,returnCode);
bool async = handler->asyncProcessing();
if (returnCode >= 400)
{
SharedPtr<SipMessage> failure(new SipMessage);
mDum.makeResponse(*failure, msg, returnCode);
if (423 == returnCode)
{
failure->header(h_StatusLine).reason() = "Interval Too Brief";
failure->header(h_MinExpires).value() = globalExpires;
}
mDum.send(failure);
delete(this);
return;
}
if (!async)
{
database->lockRecord(mAor);
mOriginalContacts = resip::SharedPtr<ContactList>(new ContactList);
database->getContacts(mAor, *mOriginalContacts);
}
// If no contacts are present in the request, this is simply a query.
if (!msg.exists(h_Contacts))
{
if (async)
{
mAsyncState = asyncStateQueryOnly;
}
handler->onQuery(getHandle(), msg);
return;
}
ParserContainer<NameAddr> contactList(msg.header(h_Contacts));
ParserContainer<NameAddr>::iterator i(contactList.begin());
ParserContainer<NameAddr>::iterator iEnd(contactList.end());
UInt64 now=Timer::getTimeSecs();
UInt32 expires=0;
for (; i != iEnd; ++i)
{
if (!i->isWellFormed())
{
SharedPtr<SipMessage> failure(new SipMessage);
mDum.makeResponse(*failure, msg, 400, "Malformed Contact");
mDum.send(failure);
if (!async)
{
database->unlockRecord(mAor);
}
delete(this);
return;
}
expires = globalExpires;
handler->getContactExpires(*i, mDum.getMasterProfile(), expires, returnCode);
// Check for "Contact: *" style deregistration
if (i->isAllContacts())
{
if (contactList.size() > 1 || expires != 0)
{
SharedPtr<SipMessage> failure(new SipMessage);
mDum.makeResponse(*failure, msg, 400, "Invalid use of 'Contact: *'");
mDum.send(failure);
if (!async)
{
database->unlockRecord(mAor);
}
delete(this);
return;
}
if (!async)
{
database->removeAor(mAor);
}
else
{
mAsyncLocalStore->removeAllContacts();
mAsyncState = asyncStateWaitingForAcceptReject;
}
handler->onRemoveAll(getHandle(), msg);
return;
}
ContactInstanceRecord rec;
rec.mContact=*i;
rec.mRegExpires=(UInt64)expires+now;
if(i->exists(p_Instance))
{
rec.mInstance=i->param(p_Instance);
}
if(!msg.empty(h_Paths))
{
rec.mSipPath=msg.header(h_Paths);
}
rec.mLastUpdated=now;
rec.mReceivedFrom=msg.getSource();
rec.mPublicAddress=Helper::getClientPublicAddress(msg);
bool hasFlow = tryFlow(rec,msg);
if(!testFlowRequirements(rec, msg, hasFlow))
{
// We have rejected the request. Bail.
if (!async)
{
database->unlockRecord(mAor);
}
delete(this);
return;
}
// Add ContactInstanceRecord to List
mRequestContacts.push_back(rec);
// Check to see if this is a removal.
if (expires == 0)
{
if (operation == REFRESH)
{
operation = REMOVE;
}
if (!async)
{
database->removeContact(mAor, rec);
}
else
{
mAsyncLocalStore->removeContact(rec);
}
}
else // Otherwise, it's an addition or refresh.
{
RegistrationPersistenceManager::update_status_t status;
InfoLog(<< "Adding " << mAor << " -> " << *i);
DebugLog(<< "Contact has tuple " << rec.mReceivedFrom << " and detected public address " << rec.mPublicAddress);
if (!async)
{
status = database->updateContact(mAor, rec);
}
else
{
status = mAsyncLocalStore->updateContact(rec);
}
if (status == RegistrationPersistenceManager::CONTACT_CREATED)
{
operation = ADD;
}
}
}
// The way this works is:
//
// - If no additions or removals are performed, this is a refresh
//
// - If at least one contact is removed and none are added, this
// is a removal.
//
// - If at least one contact is added, this is an addition, *even*
// *if* a contact was also removed.
//for async processing, need to wait for accept()/reject(). If accepted, the modifications made here will be
//sent to the user via asyncUpdateContacts(). The user then returns a final contact list, which is then processed
//and sent back in the 200.
if (async)
{
mAsyncState = asyncStateWaitingForAcceptReject;
}
switch (operation)
{
case REFRESH:
handler->onRefresh(getHandle(), msg);
return;
case REMOVE:
handler->onRemove(getHandle(), msg);
return;
case ADD:
handler->onAdd(getHandle(), msg);
return;
default:
assert(0);
}
}

| void ServerRegistration::reject | ( | int | statusCode | ) |
Reject a SIP registration.
!Warning! After calling this function from a ServerRegistrationHandle, do not access the handle as this function may delete this object. Use ServerRegistrationHandle::isValidHandle() to test if it's deleted.
Definition at line 146 of file ServerRegistration.cxx.
References resip::RegistrationPersistenceManager::addAor(), resip::ServerRegistrationHandler::asyncProcessing(), resip::SharedPtr< T >::get(), InfoLog, resip::DialogUsageManager::makeResponse(), mAor, resip::BaseUsage::mDum, mOriginalContacts, resip::DialogUsageManager::mRegistrationPersistenceManager, mRequest, resip::DialogUsageManager::mServerRegistrationHandler, resip::RegistrationPersistenceManager::removeAor(), resip::DialogUsageManager::send(), and resip::RegistrationPersistenceManager::unlockRecord().
{
InfoLog( << "rejected a registration " << mAor << " with statusCode=" << statusCode );
// First, we roll back the contact database to
// the state it was before the registration request.
// Async processing hasn't actually updated the database yet, so no need to roll back.
if (mDum.mServerRegistrationHandler && !mDum.mServerRegistrationHandler->asyncProcessing())
{
// Rollback changes, since rejected
RegistrationPersistenceManager *database = mDum.mRegistrationPersistenceManager;
database->removeAor(mAor);
if (mOriginalContacts.get())
{
database->addAor(mAor, *mOriginalContacts);
}
database->unlockRecord(mAor);
}
SharedPtr<SipMessage> failure(new SipMessage);
mDum.makeResponse(*failure, mRequest, statusCode);
failure->remove(h_Contacts);
mDum.send(failure);
delete(this);
}

| bool ServerRegistration::testFlowRequirements | ( | ContactInstanceRecord & | rec, |
| const resip::SipMessage & | msg, | ||
| bool | hasFlow | ||
| ) | const [private] |
Definition at line 509 of file ServerRegistration.cxx.
References resip::NameAddr::exists(), flowTokenNeededForSigcomp(), flowTokenNeededForTls(), resip::DialogUsageManager::makeResponse(), resip::ContactInstanceRecord::mContact, resip::BaseUsage::mDum, and resip::DialogUsageManager::send().
Referenced by processRegistration().
{
const resip::NameAddr& contact(rec.mContact);
if(contact.exists(p_Instance) && contact.exists(p_regid))
{
// Client has explicitly requested Outbound processing, which requires us
// to have a flow.
if(!hasFlow)
{
SharedPtr<SipMessage> failure(new SipMessage);
mDum.makeResponse(*failure, msg, 439);
mDum.send(failure);
return false;
}
}
if(!hasFlow && flowTokenNeededForTls(rec))
{
SharedPtr<SipMessage> failure(new SipMessage);
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.");
mDum.send(failure);
return false;
}
if(!hasFlow && flowTokenNeededForSigcomp(rec))
{
SharedPtr<SipMessage> failure(new SipMessage);
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.");
mDum.send(failure);
return false;
}
return true;
}

| bool ServerRegistration::tryFlow | ( | ContactInstanceRecord & | rec, |
| const resip::SipMessage & | msg | ||
| ) | [private] |
Definition at line 451 of file ServerRegistration.cxx.
References resip::InteropHelper::ClientNATDetectionDisabled, resip::InteropHelper::ClientNATDetectionPrivateToPublicOnly, resip::SipMessage::empty(), resip::NameAddr::exists(), resip::Uri::exists(), flowTokenNeededForSigcomp(), flowTokenNeededForTls(), resip::InteropHelper::getAssumeFirstHopSupportsOutboundEnabled(), resip::InteropHelper::getClientNATDetectionMode(), resip::InteropHelper::getOutboundSupported(), resip::InteropHelper::getRRTokenHackEnabled(), resip::SipMessage::header(), resip::Helper::isClientBehindNAT(), resip::ContactInstanceRecord::mContact, mDidOutbound, resip::ContactInstanceRecord::mReceivedFrom, resip::ContactInstanceRecord::mRegId, resip::ContactInstanceRecord::mUseFlowRouting, resip::Tuple::onlyUseExistingConnection, resip::ParserCategory::param(), and resip::RequestLine::uri().
Referenced by processRegistration().
{
// .bwc. ie. Can we assure that the connection the client is using on the
// first hop can be re-used later?
try
{
// Outbound logic
if(InteropHelper::getOutboundSupported())
{
resip::NameAddr& contact(rec.mContact);
if(contact.exists(p_Instance) && contact.exists(p_regid))
{
if(!msg.empty(h_Paths) && (msg.header(h_Paths).back().uri().exists(p_ob) ||
InteropHelper::getAssumeFirstHopSupportsOutboundEnabled()))
{
rec.mRegId=contact.param(p_regid);
// Edge-proxy is directly connected to the client, and ready to
// send traffic down the "connection" (TCP connection, or NAT
// pinhole, or what-have-you).
mDidOutbound=true;
return true;
}
else if(msg.header(h_Vias).size() == 1)
{
rec.mRegId=contact.param(p_regid);
// We are directly connected to the client.
// .bwc. In the outbound case, we should fail if the connection
// is gone. No recovery should be attempted by the server.
rec.mUseFlowRouting = true;
rec.mReceivedFrom.onlyUseExistingConnection=true;
mDidOutbound=true;
return true;
}
}
}
// Record-Route flow token hack, or client NAT detect hack; use with caution
if(msg.header(h_Vias).size() == 1) // client is directly connected to this server
{
if(InteropHelper::getRRTokenHackEnabled() ||
flowTokenNeededForTls(rec) ||
flowTokenNeededForSigcomp(rec) ||
(InteropHelper::getClientNATDetectionMode() != InteropHelper::ClientNATDetectionDisabled &&
Helper::isClientBehindNAT(msg, InteropHelper::getClientNATDetectionMode() == InteropHelper::ClientNATDetectionPrivateToPublicOnly)))
{
rec.mUseFlowRouting = true;
rec.mReceivedFrom.onlyUseExistingConnection=false;
return true;
}
}
}
catch(resip::ParseBuffer::Exception&)
{}
return false;
}

friend class DialogSet [friend] |
Definition at line 58 of file ServerRegistration.hxx.
Uri resip::ServerRegistration::mAor [private] |
Definition at line 70 of file ServerRegistration.hxx.
Referenced by accept(), asyncProcessFinalOkMsg(), dispatch(), dump(), processFinalOkMsg(), processRegistration(), and reject().
Definition at line 185 of file ServerRegistration.hxx.
Referenced by accept(), asyncProvideContacts(), and processRegistration().
Message stored during accept() call when waiting for final contact list from database.
Is eventually used as the 200Ok sent back to DUM when all is finished.
Definition at line 190 of file ServerRegistration.hxx.
Referenced by accept(), and asyncProcessFinalContacts().
Definition at line 118 of file ServerRegistration.hxx.
Referenced by accept(), asyncProcessFinalContacts(), asyncProvideContacts(), dispatch(), and processRegistration().
bool resip::ServerRegistration::mDidOutbound [private] |
Definition at line 73 of file ServerRegistration.hxx.
resip::SharedPtr<ContactList> resip::ServerRegistration::mOriginalContacts [private] |
Definition at line 71 of file ServerRegistration.hxx.
Referenced by getOriginalContacts(), processRegistration(), and reject().
Definition at line 69 of file ServerRegistration.hxx.
Referenced by accept(), asyncProvideContacts(), and reject().
ContactList resip::ServerRegistration::mRequestContacts [private] |
Definition at line 72 of file ServerRegistration.hxx.
Referenced by getRequestContacts(), and processRegistration().
1.7.5.1