01c4e1c7 |
#ifndef _RegisterCache_h_
#define _RegisterCache_h_
#include "singleton.h"
#include "hash_table.h" |
6146fb5e |
#include "atomic_types.h" |
01c4e1c7 |
|
872aabf2 |
#include "AmSipMsg.h"
#include "AmUriParser.h" |
d386f9dc |
#include "AmAppTimer.h" |
872aabf2 |
|
01c4e1c7 |
#include <string>
#include <map> |
a1232627 |
#include <memory> |
01c4e1c7 |
using std::string;
using std::map; |
a1232627 |
using std::auto_ptr; |
01c4e1c7 |
#define REG_CACHE_TABLE_POWER 10
#define REG_CACHE_TABLE_ENTRIES (1<<REG_CACHE_TABLE_POWER)
|
872aabf2 |
#define DEFAULT_REG_EXPIRES 3600
|
a1232627 |
/*
* Register cache:
* ---------------
* Data model:
* - canonical AoR <--1-to-n--> contacts
* - alias <--1-to-1--> contact
*/
|
01c4e1c7 |
struct RegBinding
{ |
872aabf2 |
// Absolute timestamp representing
// the expiration timer at the
// registrar side
long int reg_expire; |
01c4e1c7 |
// unique-id used as contact user toward the registrar
string alias; |
872aabf2 |
RegBinding()
: reg_expire(0)
{} |
01c4e1c7 |
};
|
c3b36a47 |
// Contact-URI/Public-IP -> RegBinding |
01c4e1c7 |
typedef map<string,RegBinding*> AorEntry;
|
a1232627 |
struct AliasEntry |
d386f9dc |
: public DirectAppTimer |
a1232627 |
{ |
d386f9dc |
string aor; |
a1232627 |
string contact_uri; |
d386f9dc |
string alias; |
a1232627 |
// saved state for NAT handling
string source_ip;
unsigned short source_port; |
eb80fbda |
string trsp; |
a1232627 |
// sticky interface
unsigned short local_if; |
872aabf2 |
|
9331eadf |
// User-Agent
string remote_ua;
|
872aabf2 |
// Absolute timestamp representing
// the expiration timer at the
// registered UA side
long int ua_expire;
AliasEntry()
: source_port(0), local_if(0), ua_expire(0)
{} |
d386f9dc |
// from DirectAppTimer
void fire(); |
a1232627 |
};
struct RegCacheStorageHandler
{
virtual void onDelete(const string& aor, const string& uri,
const string& alias) {}
virtual void onUpdate(const string& canon_aor, const string& alias,
long int expires, const AliasEntry& alias_update) {} |
872aabf2 |
virtual void onUpdate(const string& alias, long int ua_expires) {} |
a1232627 |
};
|
01c4e1c7 |
/**
* Hash-table bucket: |
a1232627 |
* AoR -> AorEntry |
01c4e1c7 |
*/ |
e7a5c623 |
class AorBucket |
01c4e1c7 |
: public ht_map_bucket<string,AorEntry>
{
public: |
e7a5c623 |
AorBucket(unsigned long id) |
01c4e1c7 |
: ht_map_bucket<string,AorEntry>(id)
{}
/**
* Match and retrieve the cache entry associated with the AOR passed.
* aor: canonicalized AOR
*/
AorEntry* get(const string& aor);
/* Maintenance stuff */
|
a1232627 |
void gbc(RegCacheStorageHandler* h, long int now, list<string>& alias_list);
void dump_elmt(const string& aor, const AorEntry* p_aor_entry) const; |
01c4e1c7 |
};
/**
* Hash-table bucket:
* Alias -> Contact-URI
*/
class AliasBucket
: public ht_map_bucket<string,AliasEntry>
{
public:
AliasBucket(unsigned long int id)
: ht_map_bucket<string,AliasEntry>(id)
{}
AliasEntry* getContact(const string& alias);
|
e7a5c623 |
void dump_elmt(const string& alias, const AliasEntry* ae) const;
};
class ContactBucket
: public ht_map_bucket<string,string>
{ |
676c5f2c |
typedef ht_map_bucket<string,string> Bucket;
bool insert(const string& k, string* v) {
return Bucket::insert(k,v);
}
bool remove(const string& k) {
return Bucket::remove(k);
}
|
e7a5c623 |
public:
ContactBucket(unsigned long int id)
: ht_map_bucket<string,string>(id)
{}
void insert(const string& contact_uri, const string& remote_ip,
unsigned short remote_port, const string& alias);
string getAlias(const string& contact_uri, const string& remote_ip,
unsigned short remote_port);
void remove(const string& contact_uri, const string& remote_ip,
unsigned short remote_port);
void dump_elmt(const string& key, const string* alias) const; |
01c4e1c7 |
};
|
872aabf2 |
/**
* Registrar/Reg-Caching
* parsing/processing context
*/
struct RegisterCacheCtx
: public AmObject
{
string from_aor;
bool aor_parsed;
vector<AmUriParser> contacts;
bool contacts_parsed;
unsigned int requested_expires;
bool expires_parsed;
unsigned int min_reg_expires;
unsigned int max_ua_expires;
RegisterCacheCtx()
: aor_parsed(false),
contacts_parsed(false),
requested_expires(DEFAULT_REG_EXPIRES),
expires_parsed(false),
min_reg_expires(0),
max_ua_expires(0)
{}
};
|
01c4e1c7 |
class _RegisterCache
: public AmThread
{ |
e7a5c623 |
hash_table<AorBucket> reg_cache_ht; |
01c4e1c7 |
hash_table<AliasBucket> id_idx; |
e7a5c623 |
hash_table<ContactBucket> contact_idx; |
01c4e1c7 |
|
a1232627 |
auto_ptr<RegCacheStorageHandler> storage_handler;
|
01c4e1c7 |
unsigned int gbc_bucket_id;
AmSharedVar<bool> running;
|
6146fb5e |
// stats
atomic_int active_regs;
|
01c4e1c7 |
void gbc(unsigned int bucket_id); |
89568c1a |
void removeAlias(const string& alias, bool generate_event); |
01c4e1c7 |
protected:
_RegisterCache();
~_RegisterCache();
void dispose() { stop(); }
/* AmThread interface */
void run();
void on_stop();
/**
* Returns the bucket associated with the passed contact-uri
* aor: canonicalized AOR
*/ |
e7a5c623 |
AorBucket* getAorBucket(const string& aor); |
01c4e1c7 |
/**
* Returns the bucket associated with the alias given
* alias: Contact-user
*/
AliasBucket* getAliasBucket(const string& alias);
|
e7a5c623 |
/**
* Returns the bucket associated with the contact-URI given
*/
ContactBucket* getContactBucket(const string& contact_uri,
const string& remote_ip,
unsigned short remote_port);
|
c5a996bc |
int parseAoR(RegisterCacheCtx& ctx, const AmSipRequest& req, msg_logger *logger);
int parseContacts(RegisterCacheCtx& ctx, const AmSipRequest& req, msg_logger *logger);
int parseExpires(RegisterCacheCtx& ctx, const AmSipRequest& req, msg_logger *logger); |
872aabf2 |
|
d386f9dc |
void setAliasUATimer(AliasEntry* alias_e);
void removeAliasUATimer(AliasEntry* alias_e);
|
01c4e1c7 |
public:
static string canonicalize_aor(const string& aor); |
c3b36a47 |
static string compute_alias_hash(const string& aor, const string& contact_uri,
const string& public_ip); |
01c4e1c7 |
|
a1232627 |
void setStorageHandler(RegCacheStorageHandler* h) { storage_handler.reset(h); }
|
01c4e1c7 |
/**
* Match, retrieve the contact cache entry associated with the URI passed,
* and return the alias found in the cache entry.
*
* Note: this function locks and unlocks the contact cache bucket.
*
* aor: canonical Address-of-Record
* uri: Contact-URI
*/ |
872aabf2 |
bool getAlias(const string& aor, const string& uri, |
c3b36a47 |
const string& public_ip, RegBinding& out_binding); |
01c4e1c7 |
/**
* Update contact cache entry and alias map entries.
*
* Note: this function locks and unlocks
* the contact cache bucket and
* the alias map bucket.
*
* aor: canonical Address-of-Record
* uri: Contact-URI
* alias:
*/ |
e7a5c623 |
void update(const string& alias, long int reg_expires, |
872aabf2 |
const AliasEntry& alias_update);
|
e7a5c623 |
void update(long int reg_expires, const AliasEntry& alias_update);
|
b4990d21 |
bool updateAliasExpires(const string& alias, long int ua_expires); |
01c4e1c7 |
/**
* Remove contact cache entry and alias map entries.
*
* Note: this function locks and unlocks
* the contact cache bucket and
* the alias map bucket.
*
* aor: canonical Address-of-Record
* uri: Contact-URI
* alias:
*/ |
c3b36a47 |
void remove(const string& aor, const string& uri,
const string& alias); |
01c4e1c7 |
|
872aabf2 |
void remove(const string& aor); |
01c4e1c7 |
/**
* Retrieve an alias map containing all entries related
* to a particular AOR. This is needed to support REGISTER
* with '*' contact.
*
* Note: this function locks and unlocks
* the contact cache bucket.
*
* aor: canonical Address-of-Record |
b4990d21 |
* alias_map: alias -> contact |
01c4e1c7 |
*/ |
872aabf2 |
bool getAorAliasMap(const string& aor, map<string,string>& alias_map); |
01c4e1c7 |
/**
* Retrieve the alias entry related to the given alias
*/
bool findAliasEntry(const string& alias, AliasEntry& alias_entry); |
872aabf2 |
/** |
e7a5c623 |
* Retrieve the alias entry related to the given contact-URI, remote-IP & port
*/
bool findAEByContact(const string& contact_uri, const string& remote_ip,
unsigned short remote_port, AliasEntry& ae);
/** |
872aabf2 |
* Throttle REGISTER requests
*
* Returns false if REGISTER should be forwarded:
* - if registrar binding should be renewed.
* - if source IP or port do not match the saved IP & port.
* - if the request unregisters any contact.
* - if request is not a REGISTER
*/
bool throttleRegister(RegisterCacheCtx& ctx, |
c5a996bc |
const AmSipRequest& req, |
46055a8b |
msg_logger *logger = NULL); |
872aabf2 |
/** |
fd786423 |
* Save a single REGISTER contact into cache |
872aabf2 |
*
* Returns false if failed:
* - if request is not a REGISTER.
* - more than one contact should be (un)registered. |
fd786423 |
*
* If true has been returned, the request has already
* been replied with either an error or 200 (w/ contact).
*
* Note: this function also handles binding query.
* (REGISTER w/o contacts) |
872aabf2 |
*/
bool saveSingleContact(RegisterCacheCtx& ctx, |
c5a996bc |
const AmSipRequest& req, |
46055a8b |
msg_logger *logger = NULL); |
6146fb5e |
/**
* Statistics
*/
unsigned int getActiveRegs() { return active_regs.get(); } |
01c4e1c7 |
};
typedef singleton<_RegisterCache> RegisterCache;
#endif |