JSON-RPC
Mongoose includes a set of functions to ease server-side processing by means of RPC methods.
struct mg_rpc
The RPC method handler structure. Each method has an entry in a linked list, each entry points to a string describing the pattern that will invoke it and the function that will be called to satisfy the method invocation, with a proper function argument.
struct mg_rpc {
struct mg_rpc *next; // Next in list
struct mg_str method; // Method pattern
void (*fn)(struct mg_rpc_req *); // Handler function
void *fn_data; // Handler function argument
};
struct mg_rpc_req
The RPC request descriptor. An invoked method receives a descriptor containing the request, and a pointer to a function to be called to print the output response, with a proper function argument; e.g.: mg_pfn_realloc() or mg_pfn_iobuf()
struct mg_rpc_req {
struct mg_rpc **head; // RPC handlers list head
struct mg_rpc *rpc; // RPC handler being called
mg_pfn_t pfn; // Response printing function
void *pfn_data; // Response printing function data
void *req_data; // Arbitrary request data
struct mg_str frame; // Request, e.g. {"id":1,"method":"add","params":[1,2]}
};
mg_rpc_add()
void mg_rpc_add(struct mg_rpc **head, struct mg_str method_pattern,
void (*handler)(struct mg_rpc_req *), void *handler_data);
Add the method method_pattern to the list head of RPC methods. Invoking this method will call handler and pass handler_data to it with the request (as r->fn_data in the usage example below).
Parameters:
head- the linked list pointermethod_pattern- the name of the methodhandler- the RPC function performing the action for this methodhandler_data- Arbitrary function data
NOTE: if
method_patternis an empty string, this handler will be called to process JSON-RPC responses. Handling responses might be necessary if the JSON requests are initiated by both sides.
Usage example:
struct mg_rpc *s_rpc_head = NULL;
static void rpc_sum(struct mg_rpc_req *r) {
double a = 0.0, b = 0.0;
mg_json_get_num(r->frame, "$.params[0]", &a);
mg_json_get_num(r->frame, "$.params[1]", &b);
mg_rpc_ok(r, "%g", a + b);
}
static void rpc_mul(struct mg_rpc_req *r) {//...}
mg_rpc_add(&s_rpc_head, mg_str("sum"), rpc_sum, NULL);
mg_rpc_add(&s_rpc_head, mg_str("mul"), rpc_mul, NULL);
mg_rpc_del()
void mg_rpc_del(struct mg_rpc **head, void (*handler)(struct mg_rpc_req *));
Remove the method with RPC function handler handler from the list head of RPC methods.
Parameters:
head- the linked list pointerhandler- the RPC function performing the action for this method, use NULL to deallocate all
Usage example:
struct mg_rpc *s_rpc_head = NULL;
// add methods
// ...
// Time to cleanup
mg_rpc_del(&s_rpc_head, rpc_mul); // Deallocate specific handler
mg_rpc_del(&s_rpc_head, NULL); // Deallocate all RPC handlers
mg_rpc_process()
void mg_rpc_process(struct mg_rpc_req *req);
Invoke the proper method for this request. If the requested method does not exist, mg_rpc_err() will be invoked and an error indication will be printed
Parameters:
req- a request
Usage example:
struct mg_rpc *s_rpcs = NULL; // Empty RPC list head
mg_rpc_add(&s_rpcs, mg_str("rpc.list"), mg_rpc_list, NULL); // Add rpc.list
// ... add more RPC methods
// On request, process the incoming frame
struct mg_str req = mg_str("{\"id\":1,\"method\":\"sum\",\"params\":[1,2]}");
struct mg_iobuf io = {0, 0, 0, 512}; // Empty IO buf, with 512 realloc granularity
struct mg_rpc_req r = {
.head = &s_rpcs, // RPC list head
.rpc = NULL, // This will be set by mg_rpc_process()
.pfn = mg_pfn_iobuf, // Printing function: print into the io buffer
.pfn_data = &io, // Pass our io buffer as a parameter
.req_data = NULL, // No specific request data
.frame = req, // Specify incoming frame
};
mg_rpc_process(&r);
if (io.buf != NULL) printf("Response: %s\n", (char *) io.buf);
mg_iobuf_free(&io);
mg_rpc_ok(), mg_rpc_vok()
void mg_rpc_ok(struct mg_rpc_req *, const char *fmt, ...);
void mg_rpc_vok(struct mg_rpc_req *, const char *fmt, va_list *ap);
Helper functions to print result frames
Parameters:
req- a requestfmt- format string inprintfsemantics. See mg_snprintf for the list of supported format specifiers
Usage example:
static void rpc_sum(struct mg_rpc_req *r) {
double a = 0.0, b = 0.0;
mg_json_get_num(r->frame, "$.params[0]", &a);
mg_json_get_num(r->frame, "$.params[1]", &b);
mg_rpc_ok(r, "%g", a + b);
}
mg_rpc_err(), mg_rpc_verr()
void mg_rpc_err(struct mg_rpc_req *, int code, const char *fmt, ...);
void mg_rpc_verr(struct mg_rpc_req *, int code, const char *fmt, va_list *);
Helper functions to print error frames
Parameters:
req- a requestfmt- format string inprintfsemantics. See mg_snprintf for the list of supported format specifiers
Usage example:
static void rpc_dosome(struct mg_rpc_req *r) {
...
mg_rpc_err(r, -32109, "\"%.*s not found\"", len, &r->frame.buf[offset]);
}
mg_rpc_list()
void mg_rpc_list(struct mg_rpc_req *r);
Built-in RPC method to list all registered RPC methods. This function is not usually called directly, but registered as a method.
Parameters:
req- a request
Usage example:
mg_rpc_add(&s_rpc_head, mg_str("rpc.list"), mg_rpc_list, &s_rpc_head);
(see also mg_rpc_add())