Documentation

Documentation.Development-Manual-ModAPI-Dialog-3-4 History

Hide minor edits - Show changes to markup

December 11, 2019, at 07:22 PM by liviu -
Added lines 1-285:
Documentation -> Development Manual 3.4 -> Dialog Module API

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


(:allVersions Development-Manual-ModAPI-Dialog 3.4:)


Dialog Module API

(:toc-float Table of Content:)

The Dialog module API is exported by the modules/dialog/dlg_load.h file.
The dialog module provides dialog awareness to the OpenSIPS proxy. Its functionality is to keep track of the current dialogs and to offer information about them (like how many dialogs are active).
Aside from tracking, the dialog module offers functionalities like flags and attributes per dialog (persistent data across dialog), dialog profiling and dialog termination (on timeout base or external triggered).
First, you will have to bind to the RR module's API and get the structure which you will further use. The binding function is :

(:source lang=C -link -getcode :) /* Parameters : dlgb is the API output to be further used Returns the 0 in case of success and -1 in case of failure

  • /

static inline int load_dlg_api( struct dlg_binds *dlgb );

(:sourceend:)
The dlg_binds structure is exemplified below :

(:source lang=C -link -getcode :) struct dlg_binds {

        register_dlgcb_f     register_dlgcb;
        create_dlg_f         create_dlg;
        get_dlg_f            get_dlg;
        add_profiles_f       add_profiles;
        search_dlg_profile_f search_profile;
        set_dlg_profile_f    set_profile;
        unset_dlg_profile_f  unset_profile;
        get_profile_size_f   get_profile_size;
        store_dlg_value_f    store_dlg_value;
        fetch_dlg_value_f    fetch_dlg_value;
        terminate_dlg_f      terminate_dlg;

        match_dialog_f       match_dialog;
        validate_dialog_f    validate_dialog;
        fix_route_dialog_f   fix_route_dialog;

}; (:sourceend:)
Find below the API function signatures along with their usage :

(:source lang=C -link -getcode :) /* To be used to register a new dialog based callback. The function returns 0 on success. Otherwise, -1 is returned.

Parameters :

        * struct dlg_cell *dlg : the dialog that the registered callback belongs to
        * int cb_types : The type of registered callback ( can be a bitmask of multiple callback types). The options are as follows :
                        * DLGCB_LOADED - callback will get called when a new dialog is loaded into memory at startup ( from a database ) or at runtime ( from a database via external MI call or via the binary replication interface ). This callback must be registered alone, and the dlg_cell* provided at registration time must be NULL ( since it's a global cb type, not associated to any particular dialog )
                        * DLGCB_CREATED - callback will get called when a new dialog is created. The callback will be called when the dialog is fully initialized ( create_dialog() was called either from script or from the API and the Transaction associated to the initial invite is fully initialised as well ). This callback must be registered alone, and the dlg_cell* provided at registration time must be NULL ( since it's a global cb type, not associated to any particular dialog )
                        * DLGCB_FAILED - callback will get called when a particular dialog fails to establish ( 3xx, 4xx, 5xx or 6xx reply received and relayed ). This is a per dialog callback, so the first dlg parameter MUST be provided.
                        * DLGCB_CONFIRMED - callback will get called when a particular dialog gets established ( 2xx reply received ). This is a per dialog callback, so the first dlg parameter MUST be provided.
                        * DLGCB_REQ_WITHIN - callback will get called when a sequential request is matched as belonging to a particular dialog ( either via loose_route() or match_dialog() calling from the script). This is a per dialog callback, so the first dlg parameter MUST be provided.
                        * DLGCB_TERMINATED - callback will get called when a dialog gets terminated. Reasons here are BYE routing or external Termination ( MI, API, etc ). This is a per dialog callback, so the first dlg parameter MUST be provided.
                        * DLGCB_EXPIRED - callback will get called when a dialog lives past it's assigned timeout ( see the $DLG_timeout script pvar ). This is a per dialog callback, so the first dlg parameter MUST be provided.
                        * DLGCB_EARLY - callback will get called when the first provisional reply ( 1xx ) is received for the registered dialog. This is a per dialog callback, so the first dlg parameter MUST be provided.
                        * DLGCB_RESPONSE_FWDED - callback will get called when a reply is forwarded during the initial state of the dialog setup ( usually provisional 180, 183, etc ). This is a per dialog callback, so the first dlg parameter MUST be provided.
                        * DLGCB_RESPONSE_WITHIN - callback will get called for all replies forwarded by OpenSIPS for sequential requests belonging to the current dialog. This is a per dialog callback, so the first dlg parameter MUST be provided.
                        * DLGCB_MI_CONTEXT - callback will get called when the 'dlg_list_ctx' MI function is called. Useful when modules binded to the dialog module API want to append nodes to the dlg_list_ctx MI response tree. This is a per dialog callback, so the first dlg parameter MUST be provided.
                        * DLGCB_DESTROY - callback will get called when the dialog is getting ready to be destroyed. At the time of the callback calling, the dialog is unlinked from the main hash, but it is not freed yet. This is a per dialog callback, so the first dlg parameter MUST be provided.
                        * DLGCB_SAVED - callback will get called when the dialog information is synchronized to the database ( either initial insertion, updating various fields in the DB or removing the dialog from the DB ). This is a per dialog callback, so the first dlg parameter MUST be provided.
        func - the actual callback function that will be executed.
        param - parameter that will be sent to the callback when called
        free_func - function to free the callback parameter at destroy time.
  • /

typedef int (*register_dlgcb_f)(struct dlg_cell* dlg, int cb_types,

                dialog_cb func, void *param, param_free_cb free_func);

/* callback function prototype */ typedef void (dialog_cb) (struct dlg_cell* dlg, int type,

                struct dlg_cb_params * params);

/* function to free the callback param */ typedef void (param_free_cb) (void *param);

/*

        Creates the dialog structure for the current initial INVITE message and will keep track of the call for the rest of it's lifetime.
        Returns 0 in case of success. Otherwise, -1 is returned.
        Parameters :
                msg : the initial INVITE sip message
                flags : flags altering the behavior of the create dialog. Options here are :
                        * DLG_FLAG_BYEONTIMEOUT - dialog will be terminated from the middle, by OpenSIPS, when the dialog lifetime is exceeded.
                        * DLG_FLAG_PING_CALLER - ping the caller with OPTIONS messages to detect if the call is still up
                        * DLG_FLAG_PING_CALLEE - ping the callee with OPTIONS messages to detect if the call is still up
  • /

typedef int (*create_dlg_f)(struct sip_msg *req,int flags);

/*

        Returns the current dialog pointer. In case of no created dialog or other internall errors, NULL is returned.
  • /

typedef struct dlg_cell *(*get_dlg_f) (void);

/*

        Parses and creates the provided profile definitions.
        Returns 0 in case of success. Otherwise, -1 is returned.
        Parameters :
                profiles - the NULL terminated string containing one or multiple profile definitions ( sepparated by ';' )
                has_value - whether our profies will contain values with counters, or they will be just stand-alone counters
  • /

typedef int (*add_profiles_f)(char* profiles, unsigned int has_value);

/*

        Looks up and returns the profile definition associated to the provided name. In case the profile is not found, or of internal error, NULL is returned.
        Parameters :
                name : str containing the name of a single profile definition
  • /

typedef struct dlg_profile_table* (*search_dlg_profile_f)(str *name);

/*

        Sets the current dialog to belong in the provided profile definition.
        Returns 0 in case of success, and -1 otherwise.
        Parameters :
                msg : the SIP message currently being processed
                value : the value the dialog will be associated with within the provided profile
                profile : the main profile the dialog will be linked to
                is_replicated : whether or not this dialog was originated on the current machine, or we received it via replication mechanisms. Controls whether the cachedb counters should be increased for the current dialog profile or not.
  • /

typedef int (*set_dlg_profile_f)(struct sip_msg *msg, str *value,

                        struct dlg_profile_table *profile, char is_replicated);

/*

        The opposite of the set_dlg_profile_f API function.
        Returns 0 in case of success, and -1 otherwise.
        Parameters :
                msg : the SIP message currently being processed
                value : the value the dialog will be de-associated with within the provided profile
                profile : the main profile the dialog will be un-linked from
  • /

typedef int (*unset_dlg_profile_f)(struct sip_msg *msg, str *value,

                         struct dlg_profile_table *profile);

/*

        Returns the number of dialogs belonging to the current profile.
        Parameters :
                profile : the profile definition
                value : the value to filter the profile. Can be missing, the size of all individual values within a profile will be returned.
  • /

typedef unsigned int (*get_profile_size_f)(struct dlg_profile_table *profile,

                                                                                str *value);

/*

        Stores an opaque key-value mapping inside the dialog structure, which can be fetched at a later time based on the current dialog. If the key already exists, it will be overwritten.
        Returns 0 in case of success. Otherwise, -1 is returned.
        Parameters :
                dlg : the dialog pointer to link the key to
                name : name of the key to store within the provided dialog
                val : the value to be mapped to the provided key
  • /

typedef int (*store_dlg_value_f)(struct dlg_cell *dlg,

                str *name, str *val);

/*

        Fetch a previously stored value within the provided dialog.
        Returns 0 in case of success. Otherwise, -1 is returned.
        Parameters :
                dlg : the dialog pointer to fetch the key from
                name : the name of the key to fetch
                val : output parameter, the value of the key will be stored here
                val_has_buf - whether we have a buffer allocated for fetching the key's value or not. If 0, the dialog module will return a static buffer that it reuses for all key values.
  • /

typedef int (*fetch_dlg_value_f)(struct dlg_cell *dlg,

                str *name, str *val, int val_has_buf);

/*

        Terminates an ongoing dialog ( by sending BYE messages both ways )
        Returns 0 in case of success. Otherwise, -1 is returned.
        Parameters :
                h_entry : The hash bucket ID for the dialog that we want to terminate
                h_id : The ID of the dialog element within our hash bucket
                reason : An opaque string describing the reason for terminating the dialog. Can be later fetched from the script by the user
  • /

typedef int (*terminate_dlg_f)(unsigned int h_entry, unsigned int h_id,str *reason); (:sourceend:)
See below a simple example of binding to the Dialog API from another module and running a couple of dialog related operations. (:source lang=C -link -getcode :) ...

  1. include "../dialog/dlg_load.h"

... ... struct dlg_binds my_dlgb; ... ... int mod_init(void) {

        ...
        ...
        /* load the dialog API */
        if (load_dlg_api(&my_dlgb)!=0) {
                LM_ERR("failed to find dialog API - is dialog module loaded?\n");
                goto error;
        }

        /* make sure we get notified of all upcoming created dialogs */
        if (my_dlgb.register_dlgcb(NULL,DLGCB_CREATED,new_created_dialog_cb,NULL,NULL) != 0 ) {
                LM_ERR("Failed to register initial dlg callback \n");
                goto error;
        }

        ...
        ...

}

void new_created_dialog_cb(struct dlg_cell *did, int type,

                struct dlg_cb_params * params)

{

        time_t curtime;
        str create_time_key = str_init("created_at");
        str create_time;

        time(&curtime);
        LM_INFO("Dialog was created ! \n");

        if ( my_dlgb->register_dlgcb(did,
        DLGCB_CONFIRMED, dialog_confirmed_cb, NULL, NULL) != 0) {
                LM_ERR("Failed to register CB for dialog establishment \n");
                return;
        }

        if ( my_dlgb->register_dlgcb(did,
        DLGCB_REQ_WITHIN, dialog_sequential_cb, NULL, NULL) != 0) {
                LM_ERR("Failed to register CB for dialog sequential requests \n");
                return;
        }

        create_time.s = ctime(&curtime);
        create_time.len = strlen(create_time.s);

        if ( my_dlgb.store_dlg_value(did,&create_time_key,&create_time) != 0) {
                LM_ERR("Failed to store our create string key \n");
                return;
        }

}

void dialog_confirmed_cb(struct dlg_cell *did, int type,

                struct dlg_cb_params * params)

{

        str create_time_key = str_init("created_at");
        str create_time;

        if ( my_dlgb.fetch_dlg_value(did,&create_time_key,&create_time,0) != 0 ) {
                LM_ERR("Failed to fetch our create string key \n");
                return;
        }

        LM_INFO("The dialog was created at %.*s and is now established \n",create_time.len,create_time.s);

}

void dialog_sequential_cb(struct dlg_cell *did, int type,

                struct dlg_cb_params * params)

{

        struct sip_msg *msg = msg;
        str term_reason = "we HATE options from callee :D";

        if (msg->first_line.u.request.method_value == METHOD_OPTIONS && params->dir == DLG_DIR_UPSTREAM) {
                LM_INFO("Received OPTIONS sequential from callee. Terminating DLG because %.*s\n",
                term_reason.len,term_reason.s);

                if (my_dlgb.terminate_dlg(did->h_entry,did->h_id,&term_reason) != 0) {
                        LM_ERR("Failed to terminate the dialog \n");
                }
        }

} (:sourceend:)


Page last modified on December 11, 2019, at 07:22 PM