Module: sip-router Branch: master Commit: 1e1cc81d8f7c18615b78335f889c8a3de21dac24 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=1e1cc81d...
Author: Andrei Pelinescu-Onciul andrei@iptel.org Committer: Andrei Pelinescu-Onciul andrei@iptel.org Date: Mon Jul 13 22:35:34 2009 +0200
mi_rpc: support for different "modes"
Added more rpc commands: mi_fifo - output compatible with the k mi_fifo module, when using with sercmd (e.g. sercmd -f "%v" mi_fifo which) mi_dg - output compatible with the k mi_datagram module, when using with sermcd (e.g. sercmd -f "%v" mi_dg which) mi_xmlrpc - output compatible with the k mi_xmlrpc module (should be used with the xmlrpc module)
The "mi" command was changed too: it doesn't output a leading '+' anymore on each line and it doesn't print the result code (the result code is embedded in the rpc reply, there no need to print it).
---
modules/mi_rpc/mi_rpc_mod.c | 186 +++++++++++++++++++++++++++++++++++-------- 1 files changed, 153 insertions(+), 33 deletions(-)
diff --git a/modules/mi_rpc/mi_rpc_mod.c b/modules/mi_rpc/mi_rpc_mod.c index cc3daac..007c575 100644 --- a/modules/mi_rpc/mi_rpc_mod.c +++ b/modules/mi_rpc/mi_rpc_mod.c @@ -33,14 +33,31 @@ MODULE_VERSION static str mi_rpc_indent = { "\t", 1 };
static const char* rpc_mi_exec_doc[2] = { - "Execut MI command", + "Execute MI command", 0 };
-static void rpc_mi_exec(rpc_t* rpc, void* c); + + +enum mi_rpc_print_mode { + MI_PRETTY_PRINT, + MI_FIFO_PRINT, + MI_DATAGRAM_PRINT, + MI_XMLRPC_PRINT +}; + + + +static void rpc_mi_pretty_exec(rpc_t* rpc, void* c); +static void rpc_mi_fifo_exec(rpc_t* rpc, void* c); +static void rpc_mi_dg_exec(rpc_t* rpc, void* c); +static void rpc_mi_xmlrpc_exec(rpc_t* rpc, void* c);
rpc_export_t mr_rpc[] = { - {"mi", rpc_mi_exec, rpc_mi_exec_doc, RET_ARRAY}, + {"mi", rpc_mi_pretty_exec, rpc_mi_exec_doc, RET_ARRAY}, + {"mi_fifo", rpc_mi_fifo_exec, rpc_mi_exec_doc, RET_ARRAY}, + {"mi_dg", rpc_mi_dg_exec, rpc_mi_exec_doc, RET_ARRAY}, + {"mi_xmlrpc", rpc_mi_xmlrpc_exec, rpc_mi_exec_doc, RET_ARRAY}, {0, 0, 0, 0} };
@@ -56,6 +73,8 @@ struct module_exports exports = { 0 /* Child initialization function */ };
+ + struct mi_root *mi_rpc_read_params(rpc_t *rpc, void *ctx) { struct mi_root *root; @@ -108,63 +127,136 @@ error: return 0; }
-static int mi_rpc_rprint_node(rpc_t* rpc, void* ctx, struct mi_node *node, - int level) + + +/** prints a mi node using mode. + * @return 0 on success, -1 on error (line too long) + */ +static int mi_rpc_print_node(rpc_t* rpc, void* ctx, struct mi_node* node, + enum mi_rpc_print_mode mode, char* prefix) { + static char buf[512]; + char* p; + int n; + int size; struct mi_attr *attr; + + p=buf; + *p=0; + size=sizeof(buf); + n=snprintf(p, size, "%s%.*s:: %.*s", + prefix, + node->name.len, (node->name.s)?node->name.s:"", + node->value.len, (node->value.s)?node->value.s:""); + if (n==-1 || n >= size) + goto error_buf; + p+=n; + size-=n; + for( attr=node->attributes ; attr!=NULL ; attr=attr->next ) { + n=snprintf(p, size, " %.*s=%.*s", + attr->name.len, (attr->name.s)?attr->name.s:"", + attr->value.len, (attr->value.s)?attr->value.s:""); + if (n==-1 || n >= size) + goto error_buf; + p+=n; + size-=n; + } + if (mode!=MI_PRETTY_PRINT){ + n=snprintf(p, size, "\n"); + if (n==-1 || n>= size ) + goto error_buf; + } + rpc->add(ctx, "s", buf); + return 0; +error_buf: + ERR("line too long (extra %d chars)\n", (n>=size)?n-size+1:0); + rpc->fault(ctx, 500, "Line too long"); + return -1; +} + + + +static int mi_rpc_rprint_all(rpc_t* rpc, void* ctx, struct mi_node *node, + enum mi_rpc_print_mode mode, int level) +{ char indent[32]; int i; char *p;
- if(level*mi_rpc_indent.len>=32) - { - LM_ERR("too many recursive levels for indentation\n"); - return -1; - } p = indent; - for(i=0; i<level; i++) - { - memcpy(p, mi_rpc_indent.s, mi_rpc_indent.len); - p += mi_rpc_indent.len; + switch(mode){ + case MI_FIFO_PRINT: + case MI_DATAGRAM_PRINT: + case MI_PRETTY_PRINT: + if(level*mi_rpc_indent.len>=32) + { + LM_ERR("too many recursive levels for indentation\n"); + return -1; + } + for(i=0; i<level; i++) + { + memcpy(p, mi_rpc_indent.s, mi_rpc_indent.len); + p += mi_rpc_indent.len; + } + break; + case MI_XMLRPC_PRINT: + /* no identation in this mode */ + break; } *p = 0; for( ; node ; node=node->next ) { - rpc->printf(ctx, "%s+ %.*s:: %.*s", - indent, - node->name.len, (node->name.s)?node->name.s:"", - node->value.len, (node->value.s)?node->value.s:""); - - for( attr=node->attributes ; attr!=NULL ; attr=attr->next ) { - rpc->printf(ctx, "%s%.*s - %.*s=%.*s", - indent, mi_rpc_indent.len, mi_rpc_indent.s, - attr->name.len, (attr->name.s)?attr->name.s:"", - attr->value.len, (attr->value.s)?attr->value.s:""); - } - + if (mi_rpc_print_node(rpc, ctx, node, mode, p)<0) + return -1; if (node->kids) { - if (mi_rpc_rprint_node(rpc, ctx, node->kids, level+1)<0) + if (mi_rpc_rprint_all(rpc, ctx, node->kids, mode, level+1)<0) return -1; } } return 0; }
-static int mi_rpc_print_tree(rpc_t* rpc, void* ctx, struct mi_root *tree) + + +/** build an rpc reply from an mi tree. + * @param mode - how to build the reply: mi_fifo like, mi_datagram_like, + * mi_xmlrpc ... + * @return -1 on error, 0 on success + */ +static int mi_rpc_print_tree(rpc_t* rpc, void* ctx, struct mi_root *tree, + enum mi_rpc_print_mode mode) { - rpc->printf(ctx, "%d %.*s\n", tree->code, - tree->reason.len, tree->reason.s); + switch(mode){ + case MI_FIFO_PRINT: + case MI_DATAGRAM_PRINT: + /* always success, code & reason are the part of the reply */ + rpc->printf(ctx, "%d %.*s\n", tree->code, + tree->reason.len, tree->reason.s); + break; + case MI_PRETTY_PRINT: + case MI_XMLRPC_PRINT: + /* don't print code & reason, use fault instead */ + if (tree->code<200 || tree->code> 299) { + rpc->fault(ctx, tree->code, tree->reason.s); + return -1; + } + break; + }
if (tree->node.kids) { - if (mi_rpc_rprint_node(rpc, ctx, tree->node.kids, 0)<0) + if (mi_rpc_rprint_all(rpc, ctx, tree->node.kids, mode, 0)<0) return -1; } + if (mode==MI_FIFO_PRINT){ + /* mi fifo adds an extra "\n" at the end */ + rpc->printf(ctx, "\n"); + } return 0; }
-static void rpc_mi_exec(rpc_t *rpc, void *ctx) +static void rpc_mi_exec(rpc_t *rpc, void *ctx, enum mi_rpc_print_mode mode) { str cmd; struct mi_cmd *mic; @@ -215,7 +307,7 @@ static void rpc_mi_exec(rpc_t *rpc, void *ctx)
if (mi_rpl!=MI_ROOT_ASYNC_RPL) { - mi_rpc_print_tree(rpc, ctx, mi_rpl); + mi_rpc_print_tree(rpc, ctx, mi_rpl, mode); free_mi_tree(mi_rpl); if (mi_req) free_mi_tree(mi_req); return; @@ -226,3 +318,31 @@ static void rpc_mi_exec(rpc_t *rpc, void *ctx) if (mi_req) free_mi_tree(mi_req); return; } + + + +static void rpc_mi_pretty_exec(rpc_t* rpc, void* c) +{ + rpc_mi_exec(rpc, c, MI_PRETTY_PRINT); +} + + + +static void rpc_mi_fifo_exec(rpc_t* rpc, void* c) +{ + rpc_mi_exec(rpc, c, MI_FIFO_PRINT); +} + + + +static void rpc_mi_dg_exec(rpc_t* rpc, void* c) +{ + rpc_mi_exec(rpc, c, MI_DATAGRAM_PRINT); +} + + + +static void rpc_mi_xmlrpc_exec(rpc_t* rpc, void* c) +{ + rpc_mi_exec(rpc, c, MI_XMLRPC_PRINT); +}