17#define RESIPROCATE_SUBSYSTEM Subsystem::DUM
31 mAsyncState(asyncStateNone)
53 InfoLog( <<
"accepted a registration " << mAor );
74 processFinalOkMsg(ok,contacts);
84 if (mAsyncState == asyncStateQueryOnly)
86 if (!mAsyncLocalStore.get())
92 std::unique_ptr<ContactRecordTransactionLog> log;
93 std::unique_ptr<ContactPtrList> contacts;
95 mAsyncLocalStore->releaseLog(log,contacts);
99 asyncProcessFinalOkMsg(ok,*contacts);
109 if (!mAsyncLocalStore)
116 mAsyncState = asyncStateAcceptedWaitingForFinalContactList;
118 std::unique_ptr<ContactRecordTransactionLog> log;
119 std::unique_ptr<ContactPtrList> modifiedContacts;
121 mAsyncLocalStore->releaseLog(log,modifiedContacts);
123 mAsyncOkMsg = std::shared_ptr<SipMessage>(
static_cast<SipMessage*
>(ok.
clone()));
135 mDum.makeResponse(success, mRequest, statusCode);
141 if(!mRequest.
empty(h_Paths))
155 failure.
remove(h_Contacts);
168 if (mOriginalContacts.get())
170 database->
addAor(mAor, *mOriginalContacts);
183 mDum.makeResponse(failure, mRequest, statusCode);
190 DebugLog( <<
"got a registration" );
200 DebugLog( <<
"No handler or DB - sending 405" );
202 auto failure = std::make_shared<SipMessage>();
203 mDum.makeResponse(*failure, msg, 405);
217 auto failure = std::make_shared<SipMessage>();
218 mDum.makeResponse(*failure, msg, 400);
219 failure->header(
h_StatusLine).reason() =
"Bad/unsupported scheme in To: " + mAor.
scheme();
227 mAsyncState = asyncStateWaitingForInitialContactList;
233 processRegistration(msg);
237ServerRegistration::processRegistration(
const SipMessage& msg)
242 enum {ADD, REMOVE, REFRESH} operation = REFRESH;
250 if (returnCode >= 400)
252 auto failure = std::make_shared<SipMessage>();
253 mDum.makeResponse(*failure, msg, returnCode);
254 if (423 == returnCode)
256 failure->header(
h_StatusLine).reason() =
"Interval Too Brief";
257 failure->header(h_MinExpires).value() = globalExpires;
268 mOriginalContacts = std::make_shared<ContactList>();
273 if (!msg.
exists(h_Contacts))
277 mAsyncState = asyncStateQueryOnly;
290 for (; i != iEnd; ++i)
292 if (!i->isWellFormed())
294 auto failure = std::make_shared<SipMessage>();
295 mDum.makeResponse(*failure, msg, 400,
"Malformed Contact");
305 expires = globalExpires;
309 if (i->isAllContacts())
311 if (contactList.size() > 1 || expires != 0)
313 auto failure = std::make_shared<SipMessage>();
314 mDum.makeResponse(*failure, msg, 400,
"Invalid use of 'Contact: *'");
330 mAsyncLocalStore->removeAllContacts();
331 mAsyncState = asyncStateWaitingForAcceptReject;
343 if(i->exists(p_Instance))
347 if (msg.
exists(h_UserAgent))
351 if(!msg.
empty(h_Paths))
360 bool hasFlow = tryFlow(rec,msg);
362 if(!testFlowRequirements(rec, msg, hasFlow))
374 mRequestContacts.push_back(rec);
379 if (operation == REFRESH)
390 mAsyncLocalStore->removeContact(rec);
396 InfoLog(<<
"Adding " << mAor <<
" -> " << *i);
405 status = mAsyncLocalStore->updateContact(rec);
430 mAsyncState = asyncStateWaitingForAcceptReject;
463 strm <<
"ServerRegistration " << mAor;
479 if(contact.exists(p_Instance) && contact.exists(p_regid))
484 rec.
mRegId=contact.param(p_regid);
491 else if(msg.
header(h_Vias).size() == 1)
493 rec.
mRegId=contact.param(p_regid);
506 if(msg.
header(h_Vias).size() == 1)
509 flowTokenNeededForTls(rec) ||
510 flowTokenNeededForSigcomp(rec) ||
527 catch(resip::ParseBuffer::Exception&)
539 if(!msg.
empty(h_Supporteds) &&
541 contact.exists(p_Instance) &&
542 contact.exists(p_regid))
548 auto failure = std::make_shared<SipMessage>();
549 mDum.makeResponse(*failure, msg, 439);
555 if(!hasFlow && flowTokenNeededForTls(rec))
557 auto failure = std::make_shared<SipMessage>();
558 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.");
563 if(!hasFlow && flowTokenNeededForSigcomp(rec))
565 auto failure = std::make_shared<SipMessage>();
566 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.");
581 if(contact.uri().scheme()==
"sips")
587 if(contact.uri().exists(p_transport))
606 if(contact.uri().exists(p_sigcompId))
608 if(contact.uri().exists(p_transport))
611 if(type ==
TLS || type ==
TCP)
623 DebugLog(<<
"Client is using sigcomp, but we're not sure whether this "
624 "is over a connection-oriented transport or not, because "
625 "the contact doesn't have a transport param in it. It is "
626 "possible this will work though, so we'll let it proceed."
637 if (!contacts.empty())
639 std::unique_ptr<ContactPtrList>
expired;
643 for (
const auto& rec : contacts)
680 if (!contacts.empty())
685 for (
auto& rec : contacts)
703 case asyncStateWaitingForInitialContactList:
706 mAsyncLocalStore = std::make_shared<AsyncLocalStore>(std::move(contacts));
707 mAsyncState = asyncStateProcessingRegistration;
708 processRegistration(mRequest);
711 case asyncStateWaitingForAcceptReject:
716 case asyncStateAcceptedWaitingForFinalContactList:
718 mAsyncState = asyncStateProvidedFinalContacts;
719 asyncProcessFinalContacts(std::move(contacts));
733ServerRegistration::asyncProcessFinalContacts(std::unique_ptr<resip::ContactPtrList> contacts)
743 asyncProcessFinalOkMsg(*mAsyncOkMsg,*contacts);
747 mAsyncState = asyncStateNone;
754ServerRegistration::AsyncLocalStore::create(std::unique_ptr<ContactPtrList> originalContacts)
756 mModifiedContacts = std::move(originalContacts);
761ServerRegistration::AsyncLocalStore::destroy(
void)
763 mModifiedContacts.reset();
770 if (!mModifiedContacts || !mLog)
777 for (
auto& modifiedContact : *mModifiedContacts)
779 if (modifiedContact && *modifiedContact == rec)
781 *modifiedContact = rec;
790 auto newRec = std::make_shared<ContactInstanceRecord>(rec);
794 mModifiedContacts->push_back(newRec);
802 if (!mModifiedContacts || !mLog)
809 for (
auto it = std::begin(*mModifiedContacts); it != std::end(*mModifiedContacts); ++it)
811 if ((*it) && **it == rec)
815 mModifiedContacts->erase(it);
822ServerRegistration::AsyncLocalStore::removeAllContacts()
824 if (!mModifiedContacts || !mLog)
831 mModifiedContacts->clear();
bool expired(const ContactInstanceRecord &rec)
#define resip_assert(x)
This file needs to work for both C and C++ code.
static Token outbound(Symbols::Outbound)
BaseUsageHandle getBaseHandle() const
DialogUsageManager & mDum
void send(std::shared_ptr< SipMessage > request)
std::shared_ptr< MasterProfile > & getMasterProfile()
static bool isIpAddress(const Data &ipAddress)
static bool isClientBehindNAT(const SipMessage &request, bool privateToPublicOnly=true)
Looks at SIP headers and message source for a mismatch to make an assumption that the sender is behin...
static Tuple getClientPublicAddress(const SipMessage &request)
Look at Via headers, and find the first public IP address closest to the sending client.
static bool getRRTokenHackEnabled()
static unsigned int getFlowTimerSeconds()
static bool getAssumeFirstHopSupportsOutboundEnabled()
static bool getOutboundSupported()
static InteropHelper::ClientNATDetectionMode getClientNATDetectionMode()
@ ClientNATDetectionDisabled
@ ClientNATDetectionPrivateToPublicOnly
static bool getAssumeFirstHopSupportsFlowTokensEnabled()
Represents the "name-addr" and the "addr-spec" elements in the RFC 3261 grammar.
const Data & param(const ExtensionParameter ¶m) const
Const accessor for non-natively-supported parameter types.
An iterator class (bidirectional)
Container class for ParserCategory, used by SipMessage to represent multi-valued headers (Contact,...
Abstract interface of a datastore of all registered endpoints processed by DUM.
virtual void unlockRecord(const Uri &aor)=0
virtual void lockRecord(const Uri &aor)=0
virtual update_status_t updateContact(const Uri &aor, const ContactInstanceRecord &rec)=0
virtual void removeContact(const Uri &aor, const ContactInstanceRecord &rec)=0
virtual void removeAor(const Uri &aor)=0
virtual void addAor(const Uri &aor, const ContactList &contacts)=0
virtual void getContacts(const Uri &aor, ContactList &container)=0
virtual void asyncGetContacts(ServerRegistrationHandle, const Uri &aor)
Called when a REGISTER is first received to retrieve the current list.
virtual void onRefresh(ServerRegistrationHandle, const SipMessage ®)=0
Called when registration is refreshed.
virtual void onRemoveAll(ServerRegistrationHandle, const SipMessage ®)=0
Called when all the contacts are removed using "Contact: *".
virtual void asyncUpdateContacts(ServerRegistrationHandle, const Uri &aor, std::unique_ptr< ContactPtrList > modifiedContactList, std::unique_ptr< ContactRecordTransactionLog > transactionLog)
Notifies the handler to update the current contact list for the AOR to the specified list that has be...
virtual void onAdd(ServerRegistrationHandle, const SipMessage ®)=0
Called when one or more contacts are added.
virtual void onQuery(ServerRegistrationHandle, const SipMessage ®)=0
Called when a client queries for the list of current registrations.
virtual void getContactExpires(const NameAddr &contact, const std::shared_ptr< MasterProfile > &masterProfile, uint32_t &expires, uint32_t &returnCode)
When processing a REGISTER request, return the desired expires value by processing this contact's exp...
virtual void asyncRemoveExpired(ServerRegistrationHandle, const resip::Uri &aor, std::unique_ptr< resip::ContactPtrList > contacts)
Notifies the handler to remove the entries specified in the contacts parameter.
virtual void onRemove(ServerRegistrationHandle, const SipMessage ®)=0
called when one or more specified contacts is removed
virtual void getGlobalExpires(const SipMessage &msg, const std::shared_ptr< MasterProfile > &masterProfile, uint32_t &expires, uint32_t &returnCode)
When processing a REGISTER request, return the desired expires value when processing the "Expires" he...
virtual bool asyncProcessing(void) const
If true, the registration processing will use the async* functions here and will not use the Registra...
ServerRegistrationHandle getHandle()
void reject(SipMessage &failure)
Reject a SIP registration with a specific response.
virtual ~ServerRegistration()
EncodeStream & dump(EncodeStream &strm) const override
void accept(SipMessage &ok)
Accept a SIP registration with a specific response.
bool asyncProvideContacts(std::unique_ptr< resip::ContactPtrList > contacts)
Used when useAsyncProcessing() is true.
void dispatch(const SipMessage &msg) override
Represents a SIP message.
bool isRequest() const
Returns true if message is a request, false otherwise.
bool empty(const HeaderBase &headerType) const
Returns true if the header field is present and non-empty, false otherwise.
const RequestLine & header(const RequestLineType &l) const
Returns the RequestLine. This is only valid for request messages.
bool isResponse() const
Returns true if message is a response, false otherwise.
bool exists(const HeaderBase &headerType) const
Returns true if the given header field is present, false otherwise.
const Tuple & getSource() const
Returns the source tuple that the message was received from only makes sense for messages received fr...
void remove(const HeaderBase &headerType)
Prevents a header field from being present when the message is prepared for sending to a transport.
virtual Message * clone() const
void enableFlowTimer(const resip::Tuple &flow)
static const char * Outbound
static uint64_t getTimeSecs()
Returns the current clock time in seconds.
Represents the "token" element in the RFC 3261 grammar.
bool onlyUseExistingConnection
TransportType getType() const
static TransportType toTransport(const Data &)
Converts a string representation of transport type, i.e.
bool exists(const Param< Uri > ¶mType) const
Uri getAorAsUri(TransportType transportTypeToRemoveDefaultPort=UNKNOWN_TRANSPORT) const
dcm! – add UnusedChecking(_enum) below;
StatusLineType h_StatusLine
std::deque< std::shared_ptr< ContactRecordTransaction > > ContactRecordTransactionLog
Contains a collection of database operations that were performed during REGISTER processing.
bool isSecure(TransportType type)
Returns true if passed in transport type is a secure transport protocol.
std::list< std::shared_ptr< ContactInstanceRecord > > ContactPtrList
Used to reduce copying ContactInstanceRecord objects when processing registration.
unsigned long long uint64_t
TransportType
An enumeration of transport protocols.
Handle< ServerRegistration > ServerRegistrationHandle
std::list< ContactInstanceRecord > ContactList
unsigned __int64 uint64_t