Documentation |
Documentation -> Development Manual 3.2 -> Management Interface APIThis page has been visited 869 times. Pages for other versions: devel 3.5 3.4 Older versions: 3.3 3.2 3.1
The Management Interface is the abstract layer that is commonly used to control and monitor OpenSIPS. The MI Interface supports multiple actual back-ends ( eg. FIFO, Datagram, XMLRPC, HTTP GET JSON, etc ) - due to the modularity of the interface and also due to the clear separation between the logic and the transport layer, the developer just defines the functions to be externally called, and then it is up to the OpenSIPS script writer to chose what transport he will actually use for controlling OpenSIPS.
typedef struct mi_export_ { /* the name of the function ( users will call this from their transport of choice */ char *name; /* short description of the usage of this function */ char *help; /* actual function that will get called */ mi_cmd_f *cmd; /* flags for this function. Currently options are : - MI_ASYNC_RPL_FLAG - the function has an asynchronous behaviour ( eg: MI functions that send SIP messages and wait for their reply ) - MI_NO_INPUT_FLAG - the function does not receive any parameters */ unsigned int flags; /* parameter that will be passed when the cmd function gets called */ void *param; /* the initialization function to be called by OpenSIPS ( one time ) */ mi_child_init_f *init_f; }mi_export_t; /* Example of core MI exported function */ static mi_export_t mi_core_cmds[] = { { "uptime", "prints various time information about OpenSIPS - " "when it started to run, for how long it runs", mi_uptime, MI_NO_INPUT_FLAG, 0, init_mi_uptime }, { "version", "prints the version string of a runningOpenSIPS", mi_version, MI_NO_INPUT_FLAG, 0, 0 }, { "pwd", "prints the working directory of OpenSIPS", mi_pwd, MI_NO_INPUT_FLAG, 0, 0 }, ... ... ... /* For exporting the populated array of MI functions Parameters : mod_name : the name of the module exporting these functions mis : the array of exported MI functions Returns : 0 on success, negative in case of error */ int register_mi_mod( char *mod_name, mi_export_t *mis); /* Example of usage */ if (register_mi_mod( "core", mi_core_cmds)<0) { LM_ERR("unable to register core MI cmds\n"); return -1; }
/* Parameters : input : the tree that contains the command paramenters param : the parameter provided at function registration Returns : A mi_root tree containing the function reply */ typedef struct mi_root* (mi_cmd_f)(struct mi_root *input, void *param); /* below are the used structures for representing the tree root and the tree nodes */ struct mi_root { /* int code - similar to SIP or HTTP code */ unsigned int code; /* string reason for code - similar to SIP or HTTP reason */ str reason; /* handler in case of asynchronous MI commands */ struct mi_handler *async_hdl; /* the actual root node in our tree */ struct mi_node node; }; struct mi_node { str value; str name; unsigned int flags; struct mi_node *kids; struct mi_node *next; struct mi_node *last; struct mi_attr *attributes; }; struct mi_attr{ str name; str value; struct mi_attr *next; };
/* Use for creating a new output reply tree Parameters : code : success code for this tree ( >=200<300 for success, anything else for errors ) reason : string reasons representation for the code reason_len : length of the reason parameter Returns : A new mi_root tree, or NULL in case of error. Note that this function will allocate the node in PKG and it typically has to be returned - the freeing will be done in the MI core, after the output tree is written by the transport module */ struct mi_root *init_mi_tree(unsigned int code, char *reason, int reason_len); /* Adding a new child node to our tree - typically first called to mi_root->node.kids Parameters : parent : the parent node for our newly added node flags : Current options are : MI_DUP_NAME : the name of this node needs to be duplicated in PKG MI_DUP_VALUE : the value of the current node needs to be duplicated in PKG name : the name of the current node name_len : length of the node's name value : the value of the current node value_len : length of the node's value */ struct mi_node *add_mi_node_child(struct mi_node *parent, int flags, char *name, int name_len, char *value, int value_len); /* Adding a new sibling node to one of our nodes Parameters : brother : the brother node for our newly added node flags : Current options are : MI_DUP_NAME : the name of this node needs to be duplicated in PKG MI_DUP_VALUE : the value of the current node needs to be duplicated in PKG name : the name of the current node name_len : length of the node's name value : the value of the current node value_len : length of the node's value */ struct mi_node *add_mi_node_sibling(struct mi_node *brother, int flags, char *name, int name_len, char *value, int value_len); /* Adding a new attribute to one of our nodes node : the node we will be adding the key-value attribute to flags : Current options are : MI_DUP_NAME : the name of this attribute needs to be duplicated in PKG MI_DUP_VALUE : the value of the current attribute needs to be duplicated in PKG name : the name of the current attribute name_len : length of the node's attribute name value : the value of the current value value_len : length of the node's attribute value */ struct mi_attr *add_mi_attr(struct mi_node *node, int flags, char *name, int name_len, char *value, int value_len)
struct mi_root *mi_debug(struct mi_root *cmd, void *param) { struct mi_root *rpl_tree; struct mi_node *node; char *p; int len; int new_debug; /* check the kids member of our root node - if the input root node has kids, our command was called with parameters */ node = cmd->node.kids; if (node!=NULL) { /* take the node's value and convert it to int, to make sure the parameter is valid */ if (str2sint( &node->value, &new_debug) < 0) /* if failed to convert to int, still return a RPL tree with an >=400 code and reason */ return init_mi_tree( 400, MI_SSTR(MI_BAD_PARM)); } else new_debug = *debug; /* all is good so far, initialize a new output ROOT tree which has a 200 OK code & reason */ rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK)); if (rpl_tree==0) return 0; p = sint2str((long)new_debug, &len); /* add a new node to our output tree, which the current debug level */ node = add_mi_node_child( &rpl_tree->node, MI_DUP_VALUE, MI_SSTR("DEBUG"),p, len); if (node==0) { free_mi_tree(rpl_tree); return 0; } /* if all was successful, overwrite the actual debug level, and return our tree */ *debug = new_debug; return rpl_tree; }
For more generic information on the MI Interface as well as some examples used for running MI commands with the opensipsctl utility, see the MI Interface documentation page. |