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