[sr-dev] git:master: mi_rpc: support for different "modes"

Andrei Pelinescu-Onciul andrei at iptel.org
Mon Jul 13 22:41:27 CEST 2009


Module: sip-router
Branch: master
Commit: 1e1cc81d8f7c18615b78335f889c8a3de21dac24
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=1e1cc81d8f7c18615b78335f889c8a3de21dac24

Author: Andrei Pelinescu-Onciul <andrei at iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei at 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);
+}




More information about the sr-dev mailing list