Documentation |
Documentation -> Development Manual 3.1 -> Usrloc Module APIThis page has been visited 1268 times. Pages for other versions: devel 3.5 3.4 Older versions: 3.3 3.2 3.1
The user location API can be accessed by importing the modules/usrloc/usrloc.h header file. Once imported in your OpenSIPS module, you will then have to declare a struct usrloc_api and fill in its values in the module initialization phase. Sample code: struct usrloc_api ul; static int mod_init(void) { if (load_ul_api(&ul) < 0) { LM_ERR("failed to load the user location API\n"); return -1; } }
typedef struct usrloc_api { int use_domain; enum ul_cluster_mode cluster_mode; /* whether the user location caches contacts in OpenSIPS memory */ int (*have_mem_storage) (void); /* whether the user location makes use of contact ownership tags */ int (*tags_in_use) (void); /* the NAT branch flag, as bitmask */ unsigned int nat_flag; /** * Register a new usrloc domain. If the domain already exists, a pointer * to an existing structure will be returned. * NOTE: may only be called before forking! (e.g., during mod_init()) * * @name: name of the new domain (if using a DB, it is also the table name) * @d: output variable holding the domain * * Return: 0 (success), negative otherwise */ int (*register_udomain) (const char *name, udomain_t **d); /** * Lock/Unlock the hash table entry of the given Address-of-Record. * NOTE: you MUST always lock an AoR before using any AoR or contact * manipulation functions of this API. * * @d: the usrloc domain to use * @aor: the AoR to grab/release the entry for */ void (*lock_udomain) (udomain_t *d, str *aor); void (*unlock_udomain) (udomain_t *d, str *aor); /** * Fetch a given AoR from an usrloc domain. * NOTE: remember to @release_urecord() when you are done with it! * * @d: the domain to search within * @aor: the AoR to fetch * @r: will hold the returned object if found, NULL otherwise * * Return: 0 (found), 1 (not found) otherwise */ int (*get_urecord) (udomain_t *d, str *aor, struct urecord **r); /** * Fetch a given AoR from an usrloc domain, across multiple locations. * Thus, this function is only relevant when using * cluster_mode == CM_FEDERATION_CACHEDB. The function will return success * if the AoR exists in at least one location. * * @d: the domain to search within * @aor: the AoR to fetch * @r: will hold the returned object if found, NULL otherwise * * Return: 0 (found), 1 (not found) otherwise */ int (*get_global_urecord) (udomain_t *d, str *aor, struct urecord **r); /** * Release an (urecord_t) object previously obtained through either * @get_urecord or @get_global_urecord. * * @r: the usrloc record to release * @skip_replication: set to true in order to avoid replicating an AoR * deletion event, if any, to neighboring cluster nodes */ void (*release_urecord) (urecord_t *r, char skip_replication); /** * Create and insert a new Address-of-Record into the given domain. * NOTE: will leak shared memory if the record already exists! Use * @get_urecord accordingly beforehand to prevent this. * * @d: the domain to insert the record into * @aor: the AoR to insert * @r: will hold the newly created object * @skip_replication: set to true in order to avoid replicating an AoR * insertion event to neighboring cluster nodes * * Return: 0 (success), negative otherwise */ int (*insert_urecord) (udomain_t *d, str *aor, struct urecord **r, char skip_replication); /** * Fetch a key from record-level storage. * NOTE: remember to lock the urecord beforehand. * * @r: the record to search into * @key: the key to locate * * Return: NULL on error/key not found, value pointer otherwise */ int_str_t *(*get_urecord_key) (urecord_t *r, const str *key); /** * Create or re-assign a key-value pair within record-level storage. * NOTES: * - remember to lock the urecord beforehand * - both @key and @val will be duplicated in shared memory * * @r: the record to search into * @key: the key to locate * @val: the value to set * * Return: NULL on error, new value pointer otherwise */ int_str_t *(*put_urecord_key) (urecord_t *r, const str *key, const int_str_t *val); /** * Delete a given AoR from an usrloc domain, along with all of its * contacts. * * @d: the domain to search within * @aor: the AoR to delete * @r: optional, if available -- the exact object to delete * @skip_replication: set to true in order to avoid replicating deletion * events to neighboring cluster nodes for both contact * and AoR deletions * * Return: 0 (success), negative otherwise */ int (*delete_urecord) (udomain_t *d, str *aor, struct urecord *r, char skip_replication); /** * Match a contact against a list of contacts stored in an usrloc record. * * @r: the usrloc record to search for the contact * @ct_uri: the contact URI to search * @callid: the SIP Call-ID of the pending REGISTER message * @cseq: the SIP CSeq of the pending REGISTER message * @match: how to match the pending contact against existing bindings * @c: will hold the returned contact if found or NULL * * Return: * 0 - contact found and returned in @c * 1 - contact not found * -1 - contact found, however the given @cseq is too old and you * should ignore this REGISTER * -2 - contact found, however the given @cseq is equal to the existing * one, so you should ignore this REGISTER (is it a retransmission?) */ int (*get_ucontact) (urecord_t *r, str *ct_uri, str *callid, int cseq, struct ct_match *match, ucontact_t **c); /** * Fetch a ucontact from an usrloc domain using a contact ID. * NOTE: on success, the urecord *lock will be grabbed*! * Remember to @release_urecord, followed by @unlock_udomain! * * @d: the domain to search within * @id: the contact ID, a 64-bit unsigned integer * @r: will hold the contact's usrloc record, if found * * Return: * NULL, if contact not found * pointer to the contact, if found */ ucontact_t *(*get_ucontact_from_id) (udomain_t *d, ucontact_id id, urecord_t **r); /** * Create and add a new contact to the list of contacts in @r. If * @desc_time_order is on, the contact will be simply appended at the head * of the list (most recent), otherwise in descending q-value order. * * @r: the usrloc record of the contact * @ct_uri: the SIP URI of the contact * @ci: various info pertaining to the contact, extract from the REGISTER * message (and not only!) * @c: will hold the contact, once created * @skip_replication: set to true in order to avoid replicating an "insert" * event to neighboring cluster nodes * * Return: 0 (success), negative otherwise */ int (*insert_ucontact) (urecord_t *r, str *ct_uri, ucontact_info_t *ci, ucontact_t **c, char skip_replication); /** * Update the info of an existing usrloc contact, possibly on a re-REGISTER * * @r: the usrloc record of the contact * @c: the usrloc contact to update * @ci: various info pertaining to the contact to update * @skip_replication: set to true in order to avoid replicating an "update" * event to neighboring cluster nodes * * Return: 0 (success), negative otherwise */ int (*update_ucontact) (urecord_t *r, ucontact_t *c, ucontact_info_t *ci, char skip_replication); /** * Fetch a key from contact-level storage. * NOTE: remember to lock the urecord beforehand. * * @c: the usrloc contact to search into * @key: the key to locate * * Return: NULL on error/key not found, value pointer otherwise */ int_str_t *(*get_ucontact_key) (ucontact_t *c, const str *key); /** * Create or re-assign a key-value pair within contact-level storage. * NOTES: * - remember to lock the urecord beforehand * - both @key and @val will be duplicated in shared memory * * @c: the usrloc contact to search into * @key: the key to locate * @val: the value to set * * Return: NULL on error, new value pointer otherwise */ int_str_t *(*put_ucontact_key) (ucontact_t *c, const str *key, const int_str_t *val); /** * Delete a contact from a given usrloc record. * * @r: the usrloc record * @c: the usrloc contact to delete * @skip_replication: set to true in order to avoid replicating a "delete" * event to neighboring cluster nodes * * Return: 0 (success), negative otherwise */ int (*delete_ucontact) (urecord_t *r, ucontact_t *c, char skip_replication); /** * Delete a contact from a given usrloc domain, using its hash table or * SIP coordinates. * * @d: the usrloc domain to search within * @coords: the contact ID or SIP coordinates of the contact * (see @ucontact_coords for more info) * @skip_replication: set to true in order to avoid replicating a "delete" * event to neighboring cluster nodes * * Return: 0 (success), negative otherwise */ int (*delete_ucontact_from_coords) (udomain_t *d, ucontact_coords coords, char skip_replication); /** * Compare @ucontact_coords structs @a and @b. * * Return: 0 if equal, -1 otherwise */ int (*ucontact_coords_cmp) (ucontact_coords a, ucontact_coords b); /** * Free an @ucontact_coords object. */ void (*free_ucontact_coords) (ucontact_coords coords); /** * Generate the next contact ID of a given record. Returns a different * contact ID on each new call, rotating across CLABEL_MASK values. * * @r: the usrloc record * * Return: the next contact ID */ uint64_t (*next_contact_id) (urecord_t *r); /** * Update the SIP pinging latency of a contact, i.e. the round-trip delay * of pinging a contact using a SIP OPTIONS message. * * @d: the usrloc domain to update * @coords: the SIP coordinates of the contact * @sipping_latency: new latency value, in microseconds * * Return: 0 (success), negative otherwise */ int (*update_sipping_latency) (udomain_t *d, ucontact_coords coords, int sipping_latency); /** * Raise an async registration refresh event for an usrloc contact * * @ct: the usrloc contact * @reason: short text denoting the reason for the refresh * @req_callid: Call-ID of the pending SIP request or NULL if not available */ void (*raise_ev_ct_refresh) (const ucontact_t *ct, const str *reason, const str *req_callid); /** * Easily iterate through all currently registered domains. * @d: the last fetched domain. Use a NULL value to fetch the 1st domain. * * Return: the next domain or NULL if the end of list end has been reached. */ udomain_t *(*get_next_udomain) (udomain_t *d); /** * Low-level functions to lock/unlock a hash table bucket on a given domain * @d: the domain to use * @slot: the index of the bucket, must be less than @d->size */ void (*lock_ulslot) (udomain_t *d, int slot); void (*unlock_ulslot) (udomain_t *d, int slot); /** * Return all contacts for all currently registered users in the given * domain. The function expects a buffer of sufficient length to fit all * contacts. If the buffer is exhausted, the function returns the * estimated amount of additional space needed. In this case, the caller * is expected to repeat the call using this value as the hint. * * @d: the usrloc domain to search within * @buf: the input buffer * @buf_len: the length of the buffer * @flags: flag bitmask to be used as a filter (use 0 to skip) * @part_idx / @part_max: partition the contact space. E.g.: * * to only grab the top 25% of contacts, use: "0 / 4" * * to grab all contacts, use: "0 / 1" * @pack_coords: Set to 1 to include the contact coords in the buffer, * otherwise 0. See @ucontact_coords for more info. * * The contact information is packed into the buffer as follows: * * +=======+======+=========+=======+=============+======+========+=======+ * |int |char[]|int |char[] |socket_info *|uint |proxy_l |uint64 | * +=======+======+=========+=======+=============+======+========+=======+ * |ct1.len|ct1.s |path1.len|path1.s|sock1 |flags1|nx_hop1 |coords1| * +-------+------+---------+-------+-------------+------+--------+-------+ * |ct2.len|ct2.s |path2.len|path2.s|sock2 |flags2|nx_hop2 |coords2| * +-------+------+---------+-------+-------------+------+--------+-------+ * | ... | ... | ... | ... | ... | ... | ... | ... | * +-------+------+---------+-------+-------------+------+--------+-------+ * |ctN.len|ctN.s |pathN.len|pathN.s|sockN |flagsN|nx_hopN |coordsN| * +-------+------+---------+-------+-------------+------+--------+-------+ * |0000000| * +-------+ */ int (*get_domain_ucontacts) (udomain_t *d, void *buf, int buf_len, unsigned int flags, unsigned int part_idx, unsigned int part_max, int pack_coords); /** * Similar to @get_domain_ucontacts, except it works for all current usrloc * domains, with the contacts of each domain being merged together, without * the ability to discern the domain of a given contact anymore. */ int (*get_all_ucontacts) (void *buf, int buf_len, unsigned int flags, unsigned int part_idx, unsigned int part_max, int pack_coords); /** * Subscribe to various user location create/update/delete/expire events * concerning records (AoRs) and contacts. * * @types: bitmask of callback types to register the @cb callback for * @cb: The registered callback function. Explanation of its arguments: * - @binding: depending on the callback type, you should cast it to * either (ucontact_t *) or (urecord_t *) * - @type: type of the invoked callback (e.g. UL_CONTACT_EXPIRE) * * Return: 0 (success), negative otherwise */ int (*register_ulcb) (ul_cb_type types, void (*cb) (void *binding, ul_cb_type type)); } usrloc_api_t; |
Page last modified on January 12, 2021, at 06:32 PM