1 #include <stdarg.h>
2 
3 #include "xmlrpc_config.h"
4 
5 #include "bool.h"
6 
7 #include <xmlrpc-c/base.h>
8 #include <xmlrpc-c/client.h>
9 #include <xmlrpc-c/client_int.h>
10 #include <xmlrpc-c/client_global.h>
11 
12 /*=========================================================================
13    Global Client
14 =========================================================================*/
15 
16 static struct xmlrpc_client * globalClientP;
17 static bool globalClientExists = false;
18 
19 
20 void
xmlrpc_client_init2(xmlrpc_env * const envP,int const flags,const char * const appname,const char * const appversion,const struct xmlrpc_clientparms * const clientparmsP,unsigned int const parmSize)21 xmlrpc_client_init2(xmlrpc_env *                      const envP,
22                     int                               const flags,
23                     const char *                      const appname,
24                     const char *                      const appversion,
25                     const struct xmlrpc_clientparms * const clientparmsP,
26                     unsigned int                      const parmSize) {
27 /*----------------------------------------------------------------------------
28    This function is not thread-safe.
29 -----------------------------------------------------------------------------*/
30     if (globalClientExists)
31         xmlrpc_faultf(
32             envP,
33             "Xmlrpc-c global client instance has already been created "
34             "(need to call xmlrpc_client_cleanup() before you can "
35             "reinitialize).");
36     else {
37         /* The following call is not thread-safe */
38         xmlrpc_client_setup_global_const(envP);
39         if (!envP->fault_occurred) {
40             xmlrpc_client_create(envP, flags, appname, appversion,
41                                  clientparmsP, parmSize, &globalClientP);
42             if (!envP->fault_occurred)
43                 globalClientExists = true;
44 
45             if (envP->fault_occurred)
46                 xmlrpc_client_teardown_global_const();
47         }
48     }
49 }
50 
51 
52 
53 void
xmlrpc_client_init(int const flags,const char * const appname,const char * const appversion)54 xmlrpc_client_init(int          const flags,
55                    const char * const appname,
56                    const char * const appversion) {
57 /*----------------------------------------------------------------------------
58    This function is not thread-safe.
59 -----------------------------------------------------------------------------*/
60     struct xmlrpc_clientparms clientparms;
61 
62     /* As our interface does not allow for failure, we just fail silently ! */
63 
64     xmlrpc_env env;
65     xmlrpc_env_init(&env);
66 
67     clientparms.transport = NULL;
68 
69     /* The following call is not thread-safe */
70     xmlrpc_client_init2(&env, flags,
71                         appname, appversion,
72                         &clientparms, XMLRPC_CPSIZE(transport));
73 
74     xmlrpc_env_clean(&env);
75 }
76 
77 
78 
79 void
xmlrpc_client_cleanup()80 xmlrpc_client_cleanup() {
81 /*----------------------------------------------------------------------------
82    This function is not thread-safe
83 -----------------------------------------------------------------------------*/
84     XMLRPC_ASSERT(globalClientExists);
85 
86     xmlrpc_client_destroy(globalClientP);
87 
88     globalClientExists = false;
89 
90     /* The following call is not thread-safe */
91     xmlrpc_client_teardown_global_const();
92 }
93 
94 
95 
96 static void
validateGlobalClientExists(xmlrpc_env * const envP)97 validateGlobalClientExists(xmlrpc_env * const envP) {
98 
99     if (!globalClientExists)
100         xmlrpc_faultf(envP,
101                       "Xmlrpc-c global client instance "
102                       "has not been created "
103                       "(need to call xmlrpc_client_init2()).");
104 }
105 
106 
107 
108 void
xmlrpc_client_transport_call(xmlrpc_env * const envP,void * const reserved ATTR_UNUSED,const xmlrpc_server_info * const serverP,xmlrpc_mem_block * const callXmlP,xmlrpc_mem_block ** const respXmlPP)109 xmlrpc_client_transport_call(
110     xmlrpc_env *               const envP,
111     void *                     const reserved ATTR_UNUSED,
112         /* for client handle */
113     const xmlrpc_server_info * const serverP,
114     xmlrpc_mem_block *         const callXmlP,
115     xmlrpc_mem_block **        const respXmlPP) {
116 
117     validateGlobalClientExists(envP);
118     if (!envP->fault_occurred)
119         xmlrpc_client_transport_call2(envP, globalClientP, serverP,
120                                       callXmlP, respXmlPP);
121 }
122 
123 
124 
125 xmlrpc_value *
xmlrpc_client_call(xmlrpc_env * const envP,const char * const serverUrl,const char * const methodName,const char * const format,...)126 xmlrpc_client_call(xmlrpc_env * const envP,
127                    const char * const serverUrl,
128                    const char * const methodName,
129                    const char * const format,
130                    ...) {
131 
132     xmlrpc_value * resultP;
133 
134     validateGlobalClientExists(envP);
135 
136     if (!envP->fault_occurred) {
137         va_list args;
138 
139         va_start(args, format);
140 
141         xmlrpc_client_call2f_va(envP, globalClientP, serverUrl,
142                                 methodName, format, &resultP, args);
143 
144         va_end(args);
145     }
146     return resultP;
147 }
148 
149 
150 
151 xmlrpc_value *
xmlrpc_client_call_server(xmlrpc_env * const envP,const xmlrpc_server_info * const serverInfoP,const char * const methodName,const char * const format,...)152 xmlrpc_client_call_server(xmlrpc_env *               const envP,
153                           const xmlrpc_server_info * const serverInfoP,
154                           const char *               const methodName,
155                           const char *               const format,
156                           ...) {
157 
158     xmlrpc_value * resultP;
159 
160     validateGlobalClientExists(envP);
161 
162     if (!envP->fault_occurred) {
163         va_list args;
164 
165         va_start(args, format);
166 
167         xmlrpc_client_call_server2_va(envP, globalClientP, serverInfoP,
168                                       methodName, format, args, &resultP);
169         va_end(args);
170     }
171     return resultP;
172 }
173 
174 
175 
176 xmlrpc_value *
xmlrpc_client_call_server_params(xmlrpc_env * const envP,const xmlrpc_server_info * const serverInfoP,const char * const methodName,xmlrpc_value * const paramArrayP)177 xmlrpc_client_call_server_params(
178     xmlrpc_env *               const envP,
179     const xmlrpc_server_info * const serverInfoP,
180     const char *               const methodName,
181     xmlrpc_value *             const paramArrayP) {
182 
183     xmlrpc_value * resultP;
184 
185     validateGlobalClientExists(envP);
186 
187     if (!envP->fault_occurred)
188         xmlrpc_client_call2(envP, globalClientP,
189                             serverInfoP, methodName, paramArrayP,
190                             &resultP);
191 
192     return resultP;
193 }
194 
195 
196 
197 xmlrpc_value *
xmlrpc_client_call_params(xmlrpc_env * const envP,const char * const serverUrl,const char * const methodName,xmlrpc_value * const paramArrayP)198 xmlrpc_client_call_params(xmlrpc_env *   const envP,
199                           const char *   const serverUrl,
200                           const char *   const methodName,
201                           xmlrpc_value * const paramArrayP) {
202 
203     xmlrpc_value * resultP;
204 
205     validateGlobalClientExists(envP);
206 
207     if (!envP->fault_occurred) {
208         xmlrpc_server_info * serverInfoP;
209 
210         serverInfoP = xmlrpc_server_info_new(envP, serverUrl);
211 
212         if (!envP->fault_occurred) {
213             xmlrpc_client_call2(envP, globalClientP,
214                                 serverInfoP, methodName, paramArrayP,
215                                 &resultP);
216 
217             xmlrpc_server_info_free(serverInfoP);
218         }
219     }
220     return resultP;
221 }
222 
223 
224 
225 void
xmlrpc_client_call_server_asynch_params(xmlrpc_server_info * const serverInfoP,const char * const methodName,xmlrpc_response_handler responseHandler,void * const userData,xmlrpc_value * const paramArrayP)226 xmlrpc_client_call_server_asynch_params(
227     xmlrpc_server_info * const serverInfoP,
228     const char *         const methodName,
229     xmlrpc_response_handler    responseHandler,
230     void *               const userData,
231     xmlrpc_value *       const paramArrayP) {
232 
233     xmlrpc_env env;
234 
235     xmlrpc_env_init(&env);
236 
237     validateGlobalClientExists(&env);
238 
239     if (!env.fault_occurred)
240         xmlrpc_client_start_rpc(&env, globalClientP,
241                                 serverInfoP, methodName, paramArrayP,
242                                 responseHandler, userData);
243 
244     if (env.fault_occurred) {
245         /* Unfortunately, we have no way to return an error and the
246            regular callback for a failed RPC is designed to have the
247            parameter array passed to it.  This was probably an oversight
248            of the original asynch design, but now we have to be as
249            backward compatible as possible, so we do this:
250         */
251         (*responseHandler)(serverInfoP->serverUrl,
252                            methodName, paramArrayP, userData,
253                            &env, NULL);
254     }
255     xmlrpc_env_clean(&env);
256 }
257 
258 
259 
260 void
xmlrpc_client_call_asynch(const char * const serverUrl,const char * const methodName,xmlrpc_response_handler responseHandler,void * const userData,const char * const format,...)261 xmlrpc_client_call_asynch(const char * const serverUrl,
262                           const char * const methodName,
263                           xmlrpc_response_handler responseHandler,
264                           void *       const userData,
265                           const char * const format,
266                           ...) {
267 
268     xmlrpc_env env;
269 
270     xmlrpc_env_init(&env);
271 
272     validateGlobalClientExists(&env);
273 
274     if (!env.fault_occurred) {
275         va_list args;
276 
277         va_start(args, format);
278 
279         xmlrpc_client_start_rpcf_va(&env, globalClientP,
280                                     serverUrl, methodName,
281                                     responseHandler, userData,
282                                     format, args);
283 
284         va_end(args);
285     }
286     if (env.fault_occurred)
287         (*responseHandler)(serverUrl, methodName, NULL, userData, &env, NULL);
288 
289     xmlrpc_env_clean(&env);
290 }
291 
292 
293 
294 void
xmlrpc_client_call_asynch_params(const char * const serverUrl,const char * const methodName,xmlrpc_response_handler responseHandler,void * const userData,xmlrpc_value * const paramArrayP)295 xmlrpc_client_call_asynch_params(const char *   const serverUrl,
296                                  const char *   const methodName,
297                                  xmlrpc_response_handler responseHandler,
298                                  void *         const userData,
299                                  xmlrpc_value * const paramArrayP) {
300     xmlrpc_env env;
301     xmlrpc_server_info * serverInfoP;
302 
303     xmlrpc_env_init(&env);
304 
305     serverInfoP = xmlrpc_server_info_new(&env, serverUrl);
306 
307     if (!env.fault_occurred) {
308         xmlrpc_client_call_server_asynch_params(
309             serverInfoP, methodName, responseHandler, userData, paramArrayP);
310 
311         xmlrpc_server_info_free(serverInfoP);
312     }
313     if (env.fault_occurred)
314         (*responseHandler)(serverUrl, methodName, paramArrayP, userData,
315                            &env, NULL);
316     xmlrpc_env_clean(&env);
317 }
318 
319 
320 
321 void
xmlrpc_client_call_server_asynch(xmlrpc_server_info * const serverInfoP,const char * const methodName,xmlrpc_response_handler responseHandler,void * const userData,const char * const format,...)322 xmlrpc_client_call_server_asynch(xmlrpc_server_info * const serverInfoP,
323                                  const char *         const methodName,
324                                  xmlrpc_response_handler    responseHandler,
325                                  void *               const userData,
326                                  const char *         const format,
327                                  ...) {
328 
329     xmlrpc_env env;
330 
331     validateGlobalClientExists(&env);
332 
333     if (!env.fault_occurred) {
334         va_list args;
335 
336         xmlrpc_env_init(&env);
337 
338         va_start(args, format);
339 
340         xmlrpc_client_start_rpcf_server_va(
341             &env, globalClientP, serverInfoP, methodName,
342             responseHandler, userData, format, args);
343 
344         va_end(args);
345     }
346     if (env.fault_occurred)
347         (*responseHandler)(serverInfoP->serverUrl, methodName, NULL,
348                            userData, &env, NULL);
349 
350     xmlrpc_env_clean(&env);
351 }
352 
353 
354 
355 void
xmlrpc_client_event_loop_finish_asynch(void)356 xmlrpc_client_event_loop_finish_asynch(void) {
357 
358     XMLRPC_ASSERT(globalClientExists);
359     xmlrpc_client_event_loop_finish(globalClientP);
360 }
361 
362 
363 
364 void
xmlrpc_client_event_loop_finish_asynch_timeout(unsigned long const milliseconds)365 xmlrpc_client_event_loop_finish_asynch_timeout(
366     unsigned long const milliseconds) {
367 
368     XMLRPC_ASSERT(globalClientExists);
369     xmlrpc_client_event_loop_finish_timeout(globalClientP, milliseconds);
370 }
371