< Previous by Date Date Index Next by Date >
  Thread Index Next in Thread >

[reSIProcate] upcoming changes to DUM's RegistrationPersistenceManager and ServerRegistration


Hi,

1. Currently DUMs ServerRegistration and InMemoryRegistrationDatabase both rely extensively on a very specific relationship between AORs and Contacts which is described in RegistrationPersistenceManager.hxx

Basically, there is a map of AORs and each AOR has a list of Contact URIs and an absolute expiration time.

The data structure will need to change for a variety of reasons:

- We want to support GRUU, so we need a relationship between AORs and instances (AORs have instances, which have one associated Contact per flowId). This has consequences on matching/deleting. A new registration with the same instance and flowId should replace the older one even if the Contact is different. - When we return all the possible Contacts some of these need the gruu parameter added. - When we add high availability, we will need a last updated timestamp on each "record" - I'd like us to support callee capabilities. This means we need to store fairly arbitrary header parameters from the Contact headers. We could do this by storing NameAddrs for each Contact, or by creating a separate media feature parameter list. - Outbound connections requires support for the Path header which is desirable in any case
- We want to support aliases

I propose a data structure along these lines. There is a separate list of "simple" contacts and instances. All the extra data is available. I'm not sure exactly how to maintain the alias relationships, but this is a start.

class BaseContactRecord {
   NameAddr contact;    // can contain callee caps
   time_t regExpires;
   time_t lastUpdated;
   Tuple receivedFrom;  // source transport, IP address, and port
   UriList sipPath;     // Value of SIP Path header from the Request
};

class InstanceRecord : public BaseContactRecord {
   GenUri instance;
   long clientFlowId;
   Tuple serverSessionId;   // if there is no SIP Path header, the
   // Uri gruu;  (GRUU is currently derived)
};

typedef list<BaseContactRecord> SimpleContactList;
typedef list<InstanceRecord> InstanceList;

class Aor {
   Uri aor;
   SimpleContactList contacts;
   InstanceList instances;
   UriList aliases;
};

InMemoryRegistrationDatabase can use a structure like this instead, with each alias added to the map pointing to its parent:

      typedef std::map<Uri,Aor *> database_map_t;
      database_map_t mDatabase;


2. ServerRegistration::dispatch first processes a registration by first locking then adding, updating, or deleting records in the "database", then if reject is called, we roll back the changes. accept() and reject() unlock the database. This is problematic for a number of reasons. This is a DoS bait if I ever saw it. Sending a lot of illegitimate REGISTERs can lock the database and prevent the LocationServer from accessing the locked records. I'm assuming that a proxy would either block the thread or fail requests in this case.

- We don't want Registrations to impact the actual database unless they are actually accepted - We should lock the database as briefly as possible. It would be great if we only needed write locks (we could do this if all the operations on the database were atomic)* - We want to support the registration package, so we need a hook to send notifications only when they were really accepted.
- The application might want to adjust the expiration time as well.

* We can make all the single contact operations atomic. we can treat registrations with multiple contacts as atomic, but Contact: * style de-registrations could be tricky

I propose refactoring ServerRegistration so we pass a list of operations (memory owned by DUM) in the ServerRegistrationHandlers. The application can inspect the operations and/or the original request. accept() would cause the list of operations to be committed to the database (quick lock/unlock), return the current list of registered contacts (with and without instances), and free the list of operations. reject() would free the memory. We can use the same operations for updates from other cluster members when we add high availability.

I'll take a stab at this today and tomorrow.

Comments welcome.

thanks,
-rohan