libwebsockets
Lightweight C library for HTML5 websockets
lws-jrpc.h
Go to the documentation of this file.
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  *
24  *
25  * This is a JSON-RPC parser and state management implementation that's:
26  *
27  * - Lightweight, it uses lws LEJP JSON stream parser for requests, responses,
28  * and user-defined parameter objects
29  *
30  * - Stateful... you can give it sequential input buffers randomly fragmented
31  * and it will complete when it has enough
32  *
33  * - Asynchronous... response processing can return to the event loop both
34  * while the RX is still coming and after it's all received before forming
35  * the response, eg, because it's querying on a remote connection to get the
36  * response data. Any number of RPCs can be either in flight or waiting for
37  * response processing to complete before responding.
38  *
39  * - Supports "version" extension
40  *
41  * - allows binding different method names to different callbacks
42  *
43  * - Supports both client and server roles, eg, can parse both requests and
44  * responses
45  *
46  * - No support for batch. Batching is not widely used because it doesn't
47  * add anything for the vast bulk of cases compared to sending n requests.
48  *
49  * This handles client and server RX and transaction state, creating a callback
50  * when parameters can be parsed and all of the request or notification is
51  * done.
52  *
53  * Producing JSON is usually simpler and more compact than expressing it as an
54  * object model, ie often a response can be completely formed in a single
55  * lws_snprintf(). Response JSON must be buffered on heap until the method
56  * callback is called with NULL / 0 buf len indicating that the incoming request
57  * has completed parsing.
58  *
59  */
60 
61 /* these are opaque */
62 
63 struct lws_jrpc_obj;
64 struct lws_jrpc;
65 
66 typedef enum {
72 
73 /*
74  * method name to lejp parsing handler map
75  */
76 
77 typedef struct lws_jrpc_method {
78  const char *method_name;
79  const char * const *paths;
83 
84 /*
85  * Boilerplate for forming correct requests
86  */
87 
88 /* Boilerplate to start a request */
89 #define LWSJRPCBP_REQ_START_S "{\"jsonrpc\":\"2.0\",\"method\":\"%s\""
90 /* Boilerplate to start parameters (params are left freeform for user) */
91 #define LWSJRPCBP_REQ_VERSION_S ",\"version\":\"%s\""
92 /* Boilerplate to start parameters (params are left freeform for user) */
93 #define LWSJRPCBP_REQ_PARAMS ",\"params\":"
94 /* Boilerplate to complete the result object */
95 #define LWSJRPCBP_REQ_NOTIF_END "}"
96 /* Boilerplate to complete the result object */
97 #define LWSJRPCBP_REQ_ID_END_S ",\"id\":%s}"
98 
99 /*
100  * Boilerplate for forming correct responses
101  */
102 
103 /* Boilerplate to start a result */
104 #define LWSJRPCBP_RESP_RESULT "{\"jsonrpc\":\"2.0\",\"result\":"
105 /* Boilerplate to complete the result object */
106 #define LWSJRPCBP_RESP_ID_END_S ",\"id\":%s}"
107 
108 /* Boilerplate to form an error */
109 #define LWSJRPCBP_RESP_ERROR_D "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":%d"
110 /* optional */
111 #define LWSJRPCBP_RESP_ERROR_MSG_S ",\"message\":\"%s\""
112 /* optional */
113 #define LWSJRPCBP_RESP_ERROR_DATA ",\"data\":"
114 /* required */
115 #define LWSJRPCBP_RESP_ERROR_END "}"
116 
117 /*
118  * JSONRPC Well-known Errors
119  */
120 
121 enum {
123 
124  LWSJRPCWKE__PARSE_ERROR = -32700, /* invalid JSON */
125  LWSJRPCWKE__INVALID_REQUEST = -32600, /* not valid JSONRPC object */
126  LWSJRPCWKE__METHOD_NOT_FOUND = -32601, /* method not supported */
127  LWSJRPCWKE__INVALID_PARAMS = -32602, /* parameters are invalid */
128  LWSJRPCWKE__INTERNAL_ERROR = -32603, /* internal JSONRPC error */
129  LWSJRPCWKE__SERVER_ERROR_FIRST = -32000, /* implementation-defined...*/
130  LWSJRPCWKE__SERVER_ERROR_LAST = -32099, /* ... server errors range */
131 
132  LWSJRPCE__INVALID_MEMBERS = -31000, /* reponse membs in req, vv */
133 };
134 
135 enum {
138 };
139 
140 /*
141  * APIs for the opaque JRPC request object
142  */
143 
167 lws_jrpc_obj_parse(struct lws_jrpc *jrpc, int type, void *opaque,
168  const char *buf, size_t l, struct lws_jrpc_obj **r);
169 
170 /*
171  * lws_jrpc_obj_destroy() - detach and destroy a JRPC request or response
172  *
173  * \param _r: pointer to pointer to JRPC request to detach and free
174  *
175  * Detaches the req from its JRPC context and frees it and any internal
176  * allocations.
177  */
179 lws_jrpc_obj_destroy(struct lws_jrpc_obj **_r);
180 
181 /*
182  * lws_jrpc_obj_get_opaque() - retreive the opaque pointer bound to the req
183  *
184  * \param r: pointer to pointer to JRPC request
185  *
186  * Returns the opaque pointer for a req given when it was parsed / created.
187  */
188 LWS_VISIBLE LWS_EXTERN void *
189 lws_jrpc_obj_get_opaque(const struct lws_jrpc_obj *r);
190 
191 /*
192  * lws_jrpc_obj_id() - retreive the object's id string
193  *
194  * \param r: pointer to pointer to JRPC object
195  *
196  * Returns a pointer to a correctly-typed id for use in a response; if a string,
197  * then it is already quoted, if an int or null then it's provided without
198  * quotes.
199  */
200 LWS_VISIBLE LWS_EXTERN const char *
201 lws_jrpc_obj_id(const struct lws_jrpc_obj *r);
202 
203 
204 /*
205  * APIs for the opaque JRPC context
206  */
207 
217 LWS_VISIBLE LWS_EXTERN struct lws_jrpc *
218 lws_jrpc_create(const lws_jrpc_method_t *methods, void *opaque);
219 
220 /*
221  * lws_jrpc_destroy() - destroy an allocated JRPC context
222  *
223  * \param jrpc: pointer to pointer to jrpc to destroy
224  *
225  * Destroys any ongoing reqs in the JRPC and then destroys the JRPC and sets the
226  * given pointer to NULL.
227  */
229 lws_jrpc_destroy(struct lws_jrpc **jrpc);
#define LWS_EXTERN
#define LWS_VISIBLE
lws_jrpc_cb_return_t
Definition: lws-jrpc.h:66
@ LJRPC_CBRET_CONTINUE
Definition: lws-jrpc.h:67
@ LJRPC_CBRET_FAILED
Definition: lws-jrpc.h:70
@ LJRPC_CBRET_WANT_TO_EMIT
Definition: lws-jrpc.h:68
@ LJRPC_CBRET_FINISHED
Definition: lws-jrpc.h:69
struct lws_jrpc_method lws_jrpc_method_t
LWS_VISIBLE LWS_EXTERN void * lws_jrpc_obj_get_opaque(const struct lws_jrpc_obj *r)
const char * method_name
Definition: lws-jrpc.h:78
lejp_callback cb
Definition: lws-jrpc.h:80
LWS_VISIBLE LWS_EXTERN void lws_jrpc_obj_destroy(struct lws_jrpc_obj **_r)
@ LWSJRPC_PARSE_RESPONSE
Definition: lws-jrpc.h:137
@ LWSJRPC_PARSE_REQUEST
Definition: lws-jrpc.h:136
LWS_VISIBLE LWS_EXTERN struct lws_jrpc * lws_jrpc_create(const lws_jrpc_method_t *methods, void *opaque)
LWS_VISIBLE LWS_EXTERN void lws_jrpc_destroy(struct lws_jrpc **jrpc)
@ LWSJRPCE__NO_ERROR
Definition: lws-jrpc.h:122
@ LWSJRPCWKE__SERVER_ERROR_LAST
Definition: lws-jrpc.h:130
@ LWSJRPCE__INVALID_MEMBERS
Definition: lws-jrpc.h:132
@ LWSJRPCWKE__INVALID_REQUEST
Definition: lws-jrpc.h:125
@ LWSJRPCWKE__INVALID_PARAMS
Definition: lws-jrpc.h:127
@ LWSJRPCWKE__SERVER_ERROR_FIRST
Definition: lws-jrpc.h:129
@ LWSJRPCWKE__INTERNAL_ERROR
Definition: lws-jrpc.h:128
@ LWSJRPCWKE__METHOD_NOT_FOUND
Definition: lws-jrpc.h:126
@ LWSJRPCWKE__PARSE_ERROR
Definition: lws-jrpc.h:124
LWS_VISIBLE LWS_EXTERN int lws_jrpc_obj_parse(struct lws_jrpc *jrpc, int type, void *opaque, const char *buf, size_t l, struct lws_jrpc_obj **r)
LWS_VISIBLE LWS_EXTERN const char * lws_jrpc_obj_id(const struct lws_jrpc_obj *r)
const char *const * paths
Definition: lws-jrpc.h:79
signed char(* lejp_callback)(struct lejp_ctx *ctx, char reason)
Definition: lws-lejp.h:178