Module: sip-router
Branch: master
Commit: 7bbe69bf6aa0798c674898aeb23b81249b177e34
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=7bbe69b…
Author: Daniel-Constantin Mierla <miconda(a)gmail.com>
Committer: Daniel-Constantin Mierla <miconda(a)gmail.com>
Date: Tue Sep 9 11:38:12 2014 +0200
jsonrpc-s: new fucntion jsonrpc_exec(cmd)
- execute the jsonrpc command given as parameter
- cmd has to be a full json rpc document
- example:
jsonrpc_exec('{"jsonrpc": "2.0", "method":
"dispatcher.reload", "id": 1}')
- the cmd can be a dynamic string with variables
---
modules/jsonrpc-s/jsonrpc-s_mod.c | 132 +++++++++++++++++++++++++++++++++++--
1 files changed, 127 insertions(+), 5 deletions(-)
diff --git a/modules/jsonrpc-s/jsonrpc-s_mod.c b/modules/jsonrpc-s/jsonrpc-s_mod.c
index 7f35272..ebbf4c6 100644
--- a/modules/jsonrpc-s/jsonrpc-s_mod.c
+++ b/modules/jsonrpc-s/jsonrpc-s_mod.c
@@ -27,6 +27,7 @@
#include "../../ver.h"
#include "../../trim.h"
#include "../../sr_module.h"
+#include "../../mod_fix.h"
#include "../../nonsip_hooks.h"
#include "../../modules/xhttp/api.h"
@@ -62,6 +63,7 @@ static int jsonrpc_register_rpc(void);
static int mod_init(void);
static int child_init(int rank);
static int jsonrpc_dispatch(sip_msg_t* msg, char* s1, char* s2);
+static int jsonrpc_exec(sip_msg_t* msg, char* cmd, char* s2);
/** The context of the jsonrpc request being processed.
@@ -85,7 +87,10 @@ static rpc_t func_param;
char jsonrpc_error_buf[JSONRPC_ERROR_REASON_BUF_LEN];
static cmd_export_t cmds[] = {
- {"jsonrpc_dispatch", (cmd_function)jsonrpc_dispatch, 0, 0, 0, REQUEST_ROUTE},
+ {"jsonrpc_dispatch", (cmd_function)jsonrpc_dispatch, 0, 0, 0,
+ REQUEST_ROUTE},
+ {"jsonrpc_exec", (cmd_function)jsonrpc_exec, 1, fixup_spve_null, 0,
+ ANY_ROUTE},
{0, 0, 0, 0, 0, 0}
};
@@ -126,6 +131,30 @@ static jsonrpc_error_t _jsonrpc_error_table[] = {
{0, { 0, 0 } }
};
+typedef struct jsonrpc_plain_reply {
+ int rcode; /**< reply code */
+ str rtext; /**< reply reason text */
+ str rbody; /**< reply body */
+} jsonrpc_play_reply_t;
+
+static jsonrpc_play_reply_t _jsonrpc_play_reply;
+
+static void jsonrpc_set_plain_reply(int rcode, str *rtext, str *rbody,
+ void (*free_fn)(void*))
+{
+ if(_jsonrpc_play_reply.rbody.s) {
+ free_fn(_jsonrpc_play_reply.rbody.s);
+ }
+ _jsonrpc_play_reply.rcode = rcode;
+ _jsonrpc_play_reply.rtext = *rtext;
+ if(rbody) {
+ _jsonrpc_play_reply.rbody = *rbody;
+ } else {
+ _jsonrpc_play_reply.rbody.s = NULL;
+ _jsonrpc_play_reply.rbody.len = 0;
+ }
+}
+
/** Implementation of rpc_fault function required by the management API.
*
* This function will be called whenever a management function
@@ -265,11 +294,21 @@ static int jsonrpc_send(jsonrpc_ctx_t* ctx)
rbuf.len = strlen(rbuf.s);
}
if (rbuf.s!=NULL) {
- xhttp_api.reply(ctx->msg, ctx->http_code, &ctx->http_text,
- &JSONRPC_CONTENT_TYPE_HTML, &rbuf);
+ if(ctx->msg) {
+ xhttp_api.reply(ctx->msg, ctx->http_code, &ctx->http_text,
+ &JSONRPC_CONTENT_TYPE_HTML, &rbuf);
+ } else {
+ jsonrpc_set_plain_reply(ctx->http_code, &ctx->http_text, &rbuf,
+ ctx->jrpl->free_fn);
+ }
} else {
- xhttp_api.reply(ctx->msg, ctx->http_code, &ctx->http_text,
- NULL, NULL);
+ if(ctx->msg) {
+ xhttp_api.reply(ctx->msg, ctx->http_code, &ctx->http_text,
+ NULL, NULL);
+ } else {
+ jsonrpc_set_plain_reply(ctx->http_code, &ctx->http_text, NULL,
+ ctx->jrpl->free_fn);
+ }
}
if (rbuf.s!=NULL) {
ctx->jrpl->free_fn(rbuf.s);
@@ -830,6 +869,7 @@ static int mod_init(void)
jsonrpc_register_rpc();
+ memset(&_jsonrpc_play_reply, 0, sizeof(jsonrpc_play_reply_t));
return 0;
}
@@ -922,6 +962,88 @@ send_reply:
}
+static int jsonrpc_exec(sip_msg_t* msg, char* cmd, char* s2)
+{
+ rpc_export_t* rpce;
+ jsonrpc_ctx_t* ctx;
+ int ret;
+ srjson_t *nj = NULL;
+ str val;
+ str scmd;
+
+ if(fixup_get_svalue(msg, (gparam_t*)cmd, &scmd)<0 || scmd.len<=0) {
+ LM_ERR("cannot get the rpc command parameter\n");
+ return -1;
+ }
+
+ /* initialize jsonrpc context */
+ ctx = &_jsonrpc_ctx;
+ memset(ctx, 0, sizeof(jsonrpc_ctx_t));
+ ctx->msg = NULL; /* mark it not send a reply out */
+ /* parse the jsonrpc request */
+ ctx->jreq = srjson_NewDoc(NULL);
+ if(ctx->jreq==NULL) {
+ LM_ERR("Failed to init the json document\n");
+ return -1;
+ }
+
+ ctx->jreq->buf = scmd;
+ ctx->jreq->root = srjson_Parse(ctx->jreq, ctx->jreq->buf.s);
+ if(ctx->jreq->root == NULL)
+ {
+ LM_ERR("invalid json doc [[%.*s]]\n",
+ ctx->jreq->buf.len, ctx->jreq->buf.s);
+ return -1;
+ }
+ ret = -1;
+ if (jsonrpc_init_reply(ctx) < 0) goto send_reply;
+
+ /* sanity checks on jsonrpc request */
+ nj = srjson_GetObjectItem(ctx->jreq, ctx->jreq->root, "jsonrpc");
+ if(nj==NULL) {
+ LM_ERR("missing jsonrpc field in request\n");
+ goto send_reply;
+ }
+ val.s = nj->valuestring;
+ val.len = strlen(val.s);
+ if(val.len!=3 || strncmp(val.s, "2.0", 3)!=0) {
+ LM_ERR("unsupported jsonrpc version [%.*s]\n", val.len, val.s);
+ goto send_reply;
+ }
+ /* run jsonrpc command */
+ nj = srjson_GetObjectItem(ctx->jreq, ctx->jreq->root, "method");
+ if(nj==NULL) {
+ LM_ERR("missing jsonrpc method field in request\n");
+ goto send_reply;
+ }
+ val.s = nj->valuestring;
+ val.len = strlen(val.s);
+ ctx->method = val.s;
+ rpce = find_rpc_export(ctx->method, 0);
+ if (!rpce || !rpce->function) {
+ LM_ERR("method callback not found [%.*s]\n", val.len, val.s);
+ jsonrpc_fault(ctx, 500, "Method Not Found");
+ goto send_reply;
+ }
+ ctx->flags = rpce->flags;
+ nj = srjson_GetObjectItem(ctx->jreq, ctx->jreq->root, "params");
+ if(nj!=NULL && nj->type!=srjson_Array && nj->type!=srjson_Object)
{
+ LM_ERR("params field is not an array or object\n");
+ goto send_reply;
+ }
+ if(nj!=NULL) ctx->req_node = nj->child;
+ rpce->function(&func_param, ctx);
+ ret = 1;
+
+send_reply:
+ if (!ctx->reply_sent) {
+ ret = jsonrpc_send(ctx);
+ }
+ jsonrpc_clean_context(ctx);
+ if (ret < 0) return -1;
+ return 1;
+}
+
/**
*
*/