/** * Set function table: * user declares custom functions and stores them in the table * in his high level program, then tells erpc library to use these functions. * * Erpc is platform agnostic - it knows only to parse JSON and call * method with name `fncIdx` with correct parameters. What will this method * actually do, it is on user to define. */ void erpcAddFunction(char* fncName, void (*f)(int argc, JSMN_PARAMS_t argv)) { fncIdx = fnv1a_hash((const unsigned char *)fncName) % FNC_TABLE_SIZE; fncTable[fncIdx] = f; #ifdef ERPC_DEBUG printf("Hash %d - %s\n", fncIdx, (const unsigned char*)fncName); #endif }
uint64_t RequestHandler :: compute_hash( HttpMessage& request ){ if( cache_hash_function != NULL ){ return cache_hash_function( request ); } else{ std::string ckey = request.get_method() + ":" + request.get_path(); return fnv1a_hash( ckey ); } }
/** * Parse JSON and call adequate function from lookup table */ int erpcCall(char* req, uint8_t size) { int i; int r; jsmn_parser p; jsmntok_t t[16]; /* We expect no more than 128 tokens */ jsmn_init(&p); r = jsmn_parse(&p, req, size, t, sizeof(t)/sizeof(t[0])); if (r < 0) { #ifdef ERPC_DEBUG printf("Failed to parse JSON: %d\n", r); #endif return 1; } /* Assume the top-level element is an object */ if (r < 1 || t[0].type != JSMN_OBJECT) { #ifdef ERPC_DEBUG printf("Object expected\n"); #endif return 1; } /* Loop over all keys of the root object */ for (i = 1; i < r; i++) { if (jsoneq(req, &t[i], JSONRPC_METHOD_KEY) == 0) { int size = t[i+1].end-t[i+1].start; /* We may use strndup() to fetch string value */ memcpy(method, req + t[i+1].start, t[i+1].end-t[i+1].start); method[size] = '\0'; #ifdef ERPC_DEBUG printf("- Method: %s\n", method); #endif fncIdx = fnv1a_hash(method) % FNC_TABLE_SIZE; #ifdef ERPC_DEBUG printf("- Function Table Index: %d\n", fncIdx); #endif i++; } else if (jsoneq(req, &t[i], JSONRPC_PARAMS_KEY) == 0) { int j; #ifdef ERPC_DEBUG printf("- Params:\n"); #endif /** Reset paramNb */ paramNb = 0; if (t[i+1].type != JSMN_ARRAY) { continue; /* We expect params to be an array of strings */ } for (j = 0; j < t[i+1].size; j++) { jsmntok_t *g = &t[i+j+2]; int paramSize = g->end - g->start; memcpy(params[paramNb], req + g->start, paramSize); params[paramNb][paramSize] = '\0'; #ifdef ERPC_DEBUG printf(" * %s\n", params[paramNb]); #endif paramNb++; } i += t[i+1].size + 1; } else if (jsoneq(req, &t[i], JSONRPC_REPLY_TO_KEY) == 0) { int size = t[i+1].end-t[i+1].start; /* We may want to do strtol() here to get numeric value */ memcpy(replyTo, req + t[i+1].start, size); replyTo[size] = '\0'; #ifdef ERPC_DEBUG printf("- replyTo: %s\n", replyTo); #endif i++; } else { #ifdef ERPC_DEBUG printf("Unexpected key: %.*s\n", t[i].end-t[i].start, req + t[i].start); #endif } } /** Call the function only if the pointer is not pointing on the reset * vecotr (0x0) */ if (fncTable[fncIdx] == 0) SendStatus(STATUS_UNRECOGNIZED); else fncTable[fncIdx](paramNb, params); return 0; }