[OpenSER-Devel] dialog callbacks: mi enhancements

Ovidiu Sas osas at voipembedded.com
Thu Apr 17 18:07:53 CEST 2008


Hello all,


For modules sitting on top of the dialog module it is not possible to
retrieve the call specific context out of a callback, mostly because
the pointer to the context is stored inside the dialog callback
structure.

It would make sense to enhance the existing dialog callbacks with a
new one that will be used by the mi commands to list the call specific
context of the data that is hold by the module that is sitting on top
of the dialog module.

An example is the sst module. The call specific context is:
typedef struct sst_info_st {
enum sst_flags requester;
enum sst_flags supported;
unsigned int interval;
} sst_info_t;


It would make sense to create a new mi command for the dialog module
(like dlg_enhanced_list) that will print in addition to the dialog
context, the context of each module that registered an mi callback
with the dialog module.


Here's the proposed architecture:
MI changes:
 - enhance the MI API to build an mi node out of the mi tree structure
 - enhance the MI API to insert a sibling node into the mi tree structure
dialog changes:
 - new callback: DLGCB_MI_CTX_QUERY (callback for mi query commands),
sst changes:
 - register for a DLGCB_MI_CTX_QUERY, create a node with the sst
params and pass the pointer to the node back to the dialog module (the
dialog module is responsible for inserting the node into the mi tree
structure).

The major change is in the dialog module.  The DLGCB_MI_CTX_QUERY
callback will provide a pointer for storing the pointer to the nodes
that are to be provided by the DLGCB_MI_CTX_QUERY callback consumers.
Each consumer of the DLGCB_MI_CTX_QUERY callback, will create a node
(using the new MI API) and if it is the first one that is in the list
of DLGCB_MI_CTX_QUERY callback consumers, it will simply store the
pointer to the node in the pointer provided by the DLGCB_MI_CTX_QUERY
callback.  If the consumer of the DLGCB_MI_CTX_QUERY callback, is not
the first one in the list of DLGCB_MI_CTX_QUERY callback consumers, it
will create it's own node and it will append to the existing node
(created by a previous consumer) and in the end we will have a list of
chained nodes.
After all the DLGCB_MI_CTX_QUERY callbacks are executed, the dialog
module will insert the list of chains into the existing tree.

If a DLGCB_MI_CTX_QUERY callback consumers encounter an error during
the construction of it's node, it should simply free up the allocated
memory (if any) and return.


required changes:

New callback structure:
struct dlg_cb_params {
        struct sip_msg* msg;
        unsigned int direction;
        void **param;
        void **x_param;   // <== new extra param for storing the
pointer to the mi_node
};


Pass the extra param while calling the run_dlg_callbacks:
void run_dlg_callbacks( int type , struct dlg_cell *dlg, struct sip_msg *msg,
                unsigned int dir, void** x_param);


Calling the actual callback from the mi dialog function and insert the
chain of nodes provided by the DLGCB_MI_CTX_QUERY callback consumers:
		cb_node=NULL;
		run_dlg_callbacks( DLGCB_MI_CTX_QUERY, dlg, NULL, DLG_DIR_NONE,
(void **)&cb_node );
		/* No need to check for NULL cb_node.       */
		/* It is done inside add_mi_sibling_node(). */
		add_mi_sibling_node( node1, cb_node);



Note: The existing API provided by the dialog module is unchanged.


Here's a skeleton example for a DLGCB_MI_CTX_QUERY callback consumer:
void my_dialog_mi_ctx_query_CB(struct dlg_cell *did, int type, struct
dlg_cb_params * params)
{
	struct mi_node* node;
	struct mi_node* head_node = (struct mi_node *)(*(params->x_param));
	struct mi_attr* attr;

	node = create_mi_node("my_module", 9, "", 0, MI_DUP_VALUE);
	if (node==NULL) {
		LM_ERR("oom\n");
		return;
	}

	attr = add_mi_attr(node, MI_DUP_VALUE, "requester_flags", 15, p, len);
	if(attr == NULL)
		goto error;

	if (head_node) {
		/* Previous node present, adding this one to the list. */
		add_mi_sibling_node( head_node, node);
	} else {
		/* No previous node, inserting this one. */
		*(params->x_param) = (void*)node;
	}

	return;
error:
	free_mi_node(node);
	return;
}



Comments?  Thoughts? Alternative solutions?



Regards,
Ovidiu Sas



More information about the Devel mailing list