Module: sip-router
Branch: master
Commit: 1e1cc81d8f7c18615b78335f889c8a3de21dac24
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=1e1cc81…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)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);
+}