Documentation

Documentation.Development-Manual-ModAPI-Usrloc-3-1 History

Hide minor edits - Show changes to markup

January 12, 2021, at 06:32 PM by liviu -
Changed line 35 from:
  • create, update or delete Addresses-of-Record
to:
  • create, update or delete Addresses-of-Record (which are stored within a domain)
January 12, 2021, at 06:31 PM by liviu -
Changed line 23 from:
        LM_ERR("failed to load user location API\n");
to:
        LM_ERR("failed to load the user location API\n");
January 12, 2021, at 06:31 PM by liviu -
Changed line 15 from:

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 bind its values in the module initialization phase. Sample code:

to:

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:

January 12, 2021, at 06:25 PM by liviu -
Added line 33:
  • take various decisions based on the runtime configurations of the user location module
January 12, 2021, at 06:24 PM by liviu -
Added lines 14-41:

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 bind its values in the module initialization phase. Sample code:

(:source lang=C -link -getcode :) struct usrloc_api ul;

static int mod_init(void) {

    if (load_ul_api(&ul) < 0) {
        LM_ERR("failed to load user location API\n");
        return -1;
    }

} (:sourceend:)


From here onward, you can make full use of the API, in order to:

  • define new user location domains or access existing ones
  • create, update or delete Addresses-of-Record
  • create, update or delete contacts (which are stored within an Address-of-Record)
  • subscribe to AoR events: creation / update / deletion / expiration
  • subscribe to contact events: creation / update / deletion / expiration


The C API is fully described in the usrloc.h file:

January 12, 2021, at 06:16 PM by liviu -
Changed lines 13-392 from:

(:toc-float Table of Content:)

to:

(:toc-float Table of Content:)

(:source lang=C -link -getcode :) 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; (:sourceend:)

December 11, 2019, at 07:24 PM by liviu -
Added lines 1-13:
Documentation -> Development Manual 3.1 -> Usrloc Module API

This page has been visited 986 times. (:title OpenSIPS Development - Usrloc Module API:)


(:allVersions Development-Manual-ModAPI-Usrloc 3.1:)


Usrloc Module API

(:toc-float Table of Content:)


Page last modified on January 12, 2021, at 06:32 PM