1#ifndef VRTQL_RPC_DECLARE
2#define VRTQL_RPC_DECLARE
3
4#include "message.h"
5
6#ifdef __cplusplus
7extern "C" {
8#endif
9
10//------------------------------------------------------------------------------
11// Client Side
12//------------------------------------------------------------------------------
13
14/**
15 * @file rpc.h
16 * @brief WebSocket remote procedure call implementation
17 *
18 * This file implements a simple RPC mechanism for message processing.
19 */
20
21struct vrtql_rpc;
22
23
24/**
25 * @brief Callback for out-of-band messages received during RPC call
26 * @param e The RPC environment
27 * @param m The incoming message to process
28 */
29typedef void (*vrtql_rpc_ob)(struct vrtql_rpc* rpc, vrtql_msg* m);
30
31/**
32 * @brief Callback for reconnect. This is called after successful websocket
33 * reconnection.
34 * @param e The RPC environment
35 * @return Returns true on successful reconnect, false otherwise.
36 */
37typedef bool (*vrtql_rpc_reconnect)(struct vrtql_rpc* rpc);
38
39/**
40 * @brief Struct representing a RPC environment
41 */
42typedef struct vrtql_rpc
43{
44 /**< WebSocket connection */
45 vws_cnx* cnx;
46
47 /**< The number of retries of timeout occurs (default 5) */
48 uint8_t retries;
49
50 /**> User-defined handler for out-of-band messages (default delete) */
51 vrtql_rpc_ob out_of_band;
52
53 /**> User-defined handler for reconnect */
54 vrtql_rpc_reconnect reconnect;
55
56 /**< Data from last response */
57 vws_buffer* val;
58
59 /**> User-defined data*/
60 void* data;
61
62} vrtql_rpc;
63
64/**
65 * @brief Creates a new RPC module.
66 *
67 * @param cnx The WebSocket connection to use
68 * @return A new thread RPC module.
69 */
70vrtql_rpc* vrtql_rpc_new(vws_cnx* cnx);
71
72/**
73 * @brief Frees the resources allocated to a RPC module
74 *
75 * @param rpc The RPC instance
76 */
77void vrtql_rpc_free(vrtql_rpc* rpc);
78
79/**
80 * @brief Creates random tag for message identification
81 *
82 * @param length The size (characters) of the tag to be generated
83 * @return A C string (caller from free());
84 */
85char* vrtql_rpc_tag(uint16_t length);
86
87/**
88 * @brief Low-level RPC call invocation. This takes a message as input, sends
89 * and waits for a response.
90 *
91 * @param rpc The RPC instance
92 * @param req The message to send
93 * @return The response message on success, NULL otherwise. The caller must free
94 * message with vrtql_msg_free(). If connection fails, error will have
95 * VE_SOCKET along with either VE_SEND if failure was on send or VE_RECV
96 * if failure was on receive. Caller can check by using
97 * vws_is_flag(&vws.e, VE_SEND) or vws_is_flag(&vws.e, VE_RECV).
98 */
99vrtql_msg* vrtql_rpc_exec(vrtql_rpc* rpc, vrtql_msg* req);
100
101/**
102 * @brief RPC call invocation. This takes a message as input, sends and waits
103 * for a response. It translates the response's "rc" and "msg" attributes to the
104 * vws.e.code and vws.e.text values respectively. The message content, if any,
105 * is copied into the rpc->val member.
106 *
107 * @param rpc The RPC instance
108 * @param req The message to send. This is automatically freed. Caller should
109 * NOT use this message again.
110 * @return True if the RPC call received a response. False otherwise. Call
111 * information is copies into vws.e. If connection fails, error will
112 * have VE_SOCKET along with either VE_SEND if failure was on send or
113 * VE_RECV if failure was on receive. Caller can check by using
114 * vws_is_flag(&vws.e, VE_SEND) or vws_is_flag(&vws.e, VE_RECV).
115 */
116bool vrtql_rpc_invoke(vrtql_rpc* rpc, vrtql_msg* req);
117
118//------------------------------------------------------------------------------
119// Server Side
120//------------------------------------------------------------------------------
121
122/** Abbreviation for generic RPC map This is used to store registry of modules
123 * for the module system and registry of RPC calls for each module. */
124typedef struct sc_map_sv vrtql_rpc_map;
125
126typedef struct vrtql_rpc_module
127{
128 /**< Module name. */
129 cstr name;
130
131 /**< Map of RPC calls. Key is call name. Value is vrtql_rpc_call. */
132 vrtql_rpc_map calls;
133
134 /**> User-defined data*/
135 void* data;
136
137} vrtql_rpc_module;
138
139/**
140 * @brief Struct representing a RPC environment
141 */
142typedef struct vrtql_rpc_env
143{
144 /**< The user-defined data */
145 void* data;
146
147 /**< Reference to current module */
148 vrtql_rpc_module* module;
149
150} vrtql_rpc_env;
151
152/**
153 * @brief Callback for RPC call
154 * @param e The RPC environment
155 * @param m The incoming message to process
156 */
157typedef vrtql_msg* (*vrtql_rpc_call)(vrtql_rpc_env* e, vrtql_msg* m);
158
159typedef struct vrtql_rpc_system
160{
161 /**< Map of RPC modules. Key is module name. Value is module instance. */
162 vrtql_rpc_map modules;
163
164} vrtql_rpc_system;
165
166/**
167 * @brief Creates a new RPC module.
168 *
169 * @return A new thread RPC module.
170 */
171vrtql_rpc_module* vrtql_rpc_module_new(cstr name);
172
173/**
174 * @brief Frees the resources allocated to a RPC module
175 *
176 * @param m The RPC module
177 */
178void vrtql_rpc_module_free(vrtql_rpc_module* m);
179
180/**
181 * @brief Adds an RPC to module.
182 *
183 * @param m The RPC module
184 * @param n The name of the The RPC module
185 * @param c The RPC call
186 */
187void vrtql_rpc_module_set(vrtql_rpc_module* m, cstr n, vrtql_rpc_call c);
188
189/**
190 * @brief Adds an RPC to module .
191 *
192 * @param m The RPC module
193 * @param n The name of the The RPC module
194 * @return c The RPC call if exists, NULL otherwise
195 */
196vrtql_rpc_call vrtql_rpc_module_get(vrtql_rpc_module* m, cstr n);
197
198/**
199 * @brief Creates a new RPC system.
200 *
201 * @return A new RPC system.
202 */
203vrtql_rpc_system* vrtql_rpc_system_new();
204
205/**
206 * @brief Frees the resources allocated to a RPC system
207 *
208 * @param s The RPC system
209 */
210void vrtql_rpc_system_free(vrtql_rpc_system* s);
211
212/**
213 * @brief Adds a module to a system.
214 *
215 * @param s The RPC system
216 * @param m The RPC module
217 */
218void vrtql_rpc_system_set(vrtql_rpc_system* s, vrtql_rpc_module* m);
219
220/**
221 * @brief Gets a module from a system.
222 *
223 * @param s The RPC system
224 * @param n The name of the The RPC module
225 * @return m The RPC module if exists, NULL otherwise
226 */
227vrtql_rpc_module* vrtql_rpc_system_get(vrtql_rpc_system* s, cstr n);
228
229/**
230 * @brief Creates and initializes reply message for RPC call
231 * @param m The incoming message to process
232 * @return A reply message. User takes ownership of memory and must free.
233 */
234vrtql_msg* vrtql_rpc_reply(vrtql_msg* req);
235
236/**
237 * @brief Service an RPC call
238 * @param c The RPC system instance
239 * @param e The RPC environment
240 * @param m The incoming message to process
241 */
242vrtql_msg* vrtql_rpc_service(vrtql_rpc_system* s, vrtql_rpc_env* e, vrtql_msg* m);
243
244#ifdef __cplusplus
245}
246#endif
247
248#endif /* VRTQL_RPC_DECLARE */
249