/********************************************************************\ Name: mjsonrpc_user.cxx Created by: Konstantin Olchanski Contents: handler of user-provided and experimental JSON-RPC requests \********************************************************************/ #include #include #include #include #include "mjson.h" #include "midas.h" #include "msystem.h" #include "mjsonrpc.h" #include // std::mutex // // example 1: extract request parameters, return up to 3 results // static MJsonNode* user_example1(const MJsonNode* params) { if (!params) { MJSO* doc = MJSO::I(); doc->D("example of user defined RPC method that returns up to 3 results"); doc->P("arg", MJSON_STRING, "example string argment"); doc->P("optional_arg?", MJSON_INT, "optional example integer argument"); doc->R("string", MJSON_STRING, "returns the value of \"arg\" parameter"); doc->R("integer", MJSON_INT, "returns the value of \"optional_arg\" parameter"); return doc; } MJsonNode* error = NULL; std::string arg = mjsonrpc_get_param(params, "arg", &error)->GetString(); if (error) return error; int optional_arg = mjsonrpc_get_param(params, "optional_arg", NULL)->GetInt(); if (mjsonrpc_debug) printf("user_example1(%s,%d)\n", arg.c_str(), optional_arg); return mjsonrpc_make_result("string", MJsonNode::MakeString(arg.c_str()), "integer", MJsonNode::MakeInt(optional_arg)); } // // example 2: extract request parameters, return more than 3 results // static MJsonNode* user_example2(const MJsonNode* params) { if (!params) { MJSO* doc = MJSO::I(); doc->D("example of user defined RPC method that returns more than 3 results"); doc->P("arg", MJSON_STRING, "example string argment"); doc->P("optional_arg?", MJSON_INT, "optional example integer argument"); doc->R("string1", MJSON_STRING, "returns the value of \"arg\" parameter"); doc->R("string2", MJSON_STRING, "returns \"hello\""); doc->R("string3", MJSON_STRING, "returns \"world!\""); doc->R("value1", MJSON_INT, "returns the value of \"optional_arg\" parameter"); doc->R("value2", MJSON_NUMBER, "returns 3.14"); return doc; } MJsonNode* error = NULL; std::string arg = mjsonrpc_get_param(params, "arg", &error)->GetString(); if (error) return error; int optional_arg = mjsonrpc_get_param(params, "optional_arg", NULL)->GetInt(); if (mjsonrpc_debug) printf("user_example2(%s,%d)\n", arg.c_str(), optional_arg); MJsonNode* result = MJsonNode::MakeObject(); result->AddToObject("string1", MJsonNode::MakeString(arg.c_str())); result->AddToObject("string2", MJsonNode::MakeString("hello")); result->AddToObject("string3", MJsonNode::MakeString("world!")); result->AddToObject("value1", MJsonNode::MakeInt(optional_arg)); result->AddToObject("value2", MJsonNode::MakeNumber(3.14)); return mjsonrpc_make_result(result); } // // example 3: return an error // static MJsonNode* user_example3(const MJsonNode* params) { if (!params) { MJSO* doc = MJSO::I(); doc->D("example of user defined RPC method that returns an error"); doc->P("arg", MJSON_INT, "integer value, if zero, throws a JSON-RPC error"); doc->R("status", MJSON_INT, "returns the value of \"arg\" parameter"); return doc; } MJsonNode* error = NULL; int arg = mjsonrpc_get_param(params, "arg", &error)->GetInt(); if (error) return error; if (mjsonrpc_debug) printf("user_example3(%d)\n", arg); if (arg) return mjsonrpc_make_result("status", MJsonNode::MakeInt(arg)); else return mjsonrpc_make_error(15, "example error message", "example error data"); } static MJsonNode* js_any_list_files(const MJsonNode* params) { if (!params) { MJSO* doc = MJSO::I(); doc->D("js_any_list_files"); doc->P("subdir", MJSON_STRING, "List files in /Seq/State/Path/subdir"); doc->R("status", MJSON_INT, "return status of midas library calls"); doc->R("path", MJSON_STRING, "Search path"); doc->R("fileext", MJSON_STRING, "Filename extension"); doc->R("subdirs[]", MJSON_STRING, "list of subdirectories"); doc->R("files[].filename", MJSON_STRING, "script filename"); doc->R("files[].description", MJSON_STRING, "script description"); return doc; } MJsonNode* error = NULL; std::string subdir = mjsonrpc_get_param(params, "subdir", &error)->GetString(); if (error) return error; std::string fileext = mjsonrpc_get_param(params, "fileext", &error)->GetString(); if (error) return error; std::string path = mjsonrpc_get_param(params, "path", NULL)->GetString(); if (subdir.find("..") != std::string::npos) { return mjsonrpc_make_result("status", MJsonNode::MakeInt(DB_INVALID_PARAM)); } int status; HNDLE hDB; status = cm_get_experiment_database(&hDB, NULL); if (status != DB_SUCCESS) { return mjsonrpc_make_result("status", MJsonNode::MakeInt(status)); } // std::string path; // If path is not provided get from ODB if (path == "") { status = db_get_value_string(hDB, 0, "/Sequencer/State/Path", 0, &path, FALSE); } if (status != DB_SUCCESS) { return mjsonrpc_make_result("status", MJsonNode::MakeInt(status)); } path = cm_expand_env(path.c_str()); if (subdir.length() > 0) { if (path[path.length()-1] != DIR_SEPARATOR) { path += DIR_SEPARATOR_STR; } path += subdir; } char* flist = NULL; //printf("path: [%s]\n", path.c_str()); MJsonNode* s = MJsonNode::MakeArray(); /*---- go over subdirectories ----*/ int n = ss_dir_find(path.c_str(), "*", &flist); for (int i=0 ; iAddToArray(MJsonNode::MakeString(flist+i*MAX_STRING_LENGTH)); } } MJsonNode* f = MJsonNode::MakeArray(); /*---- go over files in path ----*/ n = ss_file_find(path.c_str(), fileext.c_str(), &flist); for (int i=0 ; iAddToObject("filename", MJsonNode::MakeString(flist+i*MAX_STRING_LENGTH)); o->AddToObject("description", MJsonNode::MakeString("description")); f->AddToArray(o); #if 0 char comment[512]; comment[0] = 0; strlcpy(str, path, sizeof(str)); if (strlen(str)>1 && str[strlen(str)-1] != DIR_SEPARATOR) strlcat(str, DIR_SEPARATOR_STR, sizeof(str)); strlcat(str, flist+i*MAX_STRING_LENGTH, sizeof(str)); if (msl_parse(str, error, sizeof(error), &error_line)) { if (strchr(str, '.')) { *strchr(str, '.') = 0; strlcat(str, ".xml", sizeof(str)); } comment[0] = 0; if (pnseq) { mxml_free_tree(pnseq); pnseq = NULL; } pnseq = mxml_parse_file(str, error, sizeof(error), &error_line); if (error[0]) { strlcpy(comment, error, sizeof(comment)); } else { if (pnseq) { pn = mxml_find_node(pnseq, "RunSequence/Comment"); if (pn) strlcpy(comment, mxml_get_value(pn), sizeof(comment)); else strcpy(comment, ""); } } if (pnseq) { mxml_free_tree(pnseq); pnseq = NULL; } } else { sprintf(comment, "Error in MSL: %s", error); } strsubst(comment, sizeof(comment), "\"", "\\\'"); r->rsprintf("\n", flist+i*MAX_STRING_LENGTH); #endif } free(flist); flist = NULL; MJsonNode* r = MJsonNode::MakeObject(); r->AddToObject("status", MJsonNode::MakeInt(SUCCESS)); ss_repair_utf8(path); r->AddToObject("path", MJsonNode::MakeString(path.c_str())); r->AddToObject("subdirs", s); r->AddToObject("files", f); return mjsonrpc_make_result(r); } // // to create your own rpc method handler, copy one of the examples here, register it in user_init below // // // user_init function is called at startup time to register user rpc method handlers // void mjsonrpc_user_init() { if (mjsonrpc_debug) { printf("mjsonrpc_user_init!\n"); } // add user functions to the rpc list mjsonrpc_add_handler("user_example1", user_example1); mjsonrpc_add_handler("user_example2", user_example2); mjsonrpc_add_handler("user_example3", user_example3); mjsonrpc_add_handler("any_list_files", js_any_list_files, true); } /* emacs * Local Variables: * tab-width: 8 * c-basic-offset: 3 * indent-tabs-mode: nil * End: */