initial load of upstream version 1.06.32
[xmlrpc-c] / src / xmlrpc_client_global.c
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 
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
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 
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
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
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 static void
126 clientCall_va(xmlrpc_env *               const envP,
127               const xmlrpc_server_info * const serverInfoP,
128               const char *               const methodName,
129               const char *               const format,
130               va_list                          args,
131               xmlrpc_value **            const resultPP) {
132
133     validateGlobalClientExists(envP);
134     if (!envP->fault_occurred) {
135         xmlrpc_value * paramArrayP;
136         const char * suffix;
137         
138         xmlrpc_build_value_va(envP, format, args, &paramArrayP, &suffix);
139         
140         if (!envP->fault_occurred) {
141             if (*suffix != '\0')
142                 xmlrpc_faultf(envP, "Junk after the argument "
143                               "specifier: '%s'.  "
144                               "There must be exactly one arument.",
145                               suffix);
146             else
147                 xmlrpc_client_call2(envP, globalClientP, serverInfoP,
148                                     methodName, paramArrayP, resultPP);
149             
150             xmlrpc_DECREF(paramArrayP);
151         }
152     }
153 }
154
155
156
157 xmlrpc_value * 
158 xmlrpc_client_call(xmlrpc_env * const envP,
159                    const char * const serverUrl,
160                    const char * const methodName,
161                    const char * const format,
162                    ...) {
163
164     xmlrpc_value * resultP;
165     
166     xmlrpc_server_info * serverInfoP;
167
168     serverInfoP = xmlrpc_server_info_new(envP, serverUrl);
169         
170     if (!envP->fault_occurred) {
171         va_list args;
172         va_start(args, format);
173     
174         clientCall_va(envP, serverInfoP, methodName, format, args, &resultP);
175
176         va_end(args);
177         xmlrpc_server_info_free(serverInfoP);
178     }
179     
180     return resultP;
181 }
182
183
184
185 xmlrpc_value * 
186 xmlrpc_client_call_server(xmlrpc_env *               const envP,
187                           const xmlrpc_server_info * const serverP,
188                           const char *               const methodName,
189                           const char *               const format, 
190                           ...) {
191
192     va_list args;
193     xmlrpc_value * resultP;
194
195     va_start(args, format);
196     clientCall_va(envP, serverP, methodName, format, args, &resultP);
197     va_end(args);
198
199     return resultP;
200 }
201
202
203
204 xmlrpc_value *
205 xmlrpc_client_call_server_params(
206     xmlrpc_env *               const envP,
207     const xmlrpc_server_info * const serverInfoP,
208     const char *               const methodName,
209     xmlrpc_value *             const paramArrayP) {
210
211     xmlrpc_value * resultP;
212
213     validateGlobalClientExists(envP);
214
215     if (!envP->fault_occurred)
216         xmlrpc_client_call2(envP, globalClientP,
217                             serverInfoP, methodName, paramArrayP,
218                             &resultP);
219
220     return resultP;
221 }
222
223
224
225 xmlrpc_value * 
226 xmlrpc_client_call_params(xmlrpc_env *   const envP,
227                           const char *   const serverUrl,
228                           const char *   const methodName,
229                           xmlrpc_value * const paramArrayP) {
230
231     xmlrpc_value * resultP;
232
233     validateGlobalClientExists(envP);
234
235     if (!envP->fault_occurred) {
236         xmlrpc_server_info * serverInfoP;
237
238         serverInfoP = xmlrpc_server_info_new(envP, serverUrl);
239         
240         if (!envP->fault_occurred) {
241             xmlrpc_client_call2(envP, globalClientP,
242                                 serverInfoP, methodName, paramArrayP,
243                                 &resultP);
244             
245             xmlrpc_server_info_free(serverInfoP);
246         }
247     }
248     return resultP;
249 }                            
250
251
252
253 void 
254 xmlrpc_client_call_server_asynch_params(
255     xmlrpc_server_info * const serverInfoP,
256     const char *         const methodName,
257     xmlrpc_response_handler    responseHandler,
258     void *               const userData,
259     xmlrpc_value *       const paramArrayP) {
260
261     xmlrpc_env env;
262
263     xmlrpc_env_init(&env);
264
265     validateGlobalClientExists(&env);
266
267     if (!env.fault_occurred)
268         xmlrpc_client_start_rpc(&env, globalClientP,
269                                 serverInfoP, methodName, paramArrayP,
270                                 responseHandler, userData);
271
272     if (env.fault_occurred) {
273         /* Unfortunately, we have no way to return an error and the
274            regular callback for a failed RPC is designed to have the
275            parameter array passed to it.  This was probably an oversight
276            of the original asynch design, but now we have to be as
277            backward compatible as possible, so we do this:
278         */
279         (*responseHandler)(serverInfoP->_server_url,
280                            methodName, paramArrayP, userData,
281                            &env, NULL);
282     }
283     xmlrpc_env_clean(&env);
284 }
285
286
287
288 void 
289 xmlrpc_client_call_asynch(const char * const serverUrl,
290                           const char * const methodName,
291                           xmlrpc_response_handler responseHandler,
292                           void *       const userData,
293                           const char * const format,
294                           ...) {
295
296     xmlrpc_env env;
297
298     xmlrpc_env_init(&env);
299
300     validateGlobalClientExists(&env);
301
302     if (!env.fault_occurred) {
303         xmlrpc_value * paramArrayP;
304         const char * suffix;
305         va_list args;
306     
307         va_start(args, format);
308         xmlrpc_build_value_va(&env, format, args, &paramArrayP, &suffix);
309         va_end(args);
310     
311         if (!env.fault_occurred) {
312             if (*suffix != '\0')
313                 xmlrpc_faultf(&env, "Junk after the argument "
314                               "specifier: '%s'.  "
315                               "There must be exactly one arument.",
316                               suffix);
317             else
318                 xmlrpc_client_call_asynch_params(
319                     serverUrl, methodName, responseHandler, userData,
320                     paramArrayP);
321         }
322     }
323     if (env.fault_occurred)
324         (*responseHandler)(serverUrl, methodName, NULL, userData, &env, NULL);
325
326     xmlrpc_env_clean(&env);
327 }
328
329
330
331 void
332 xmlrpc_client_call_asynch_params(const char *   const serverUrl,
333                                  const char *   const methodName,
334                                  xmlrpc_response_handler responseHandler,
335                                  void *         const userData,
336                                  xmlrpc_value * const paramArrayP) {
337     xmlrpc_env env;
338     xmlrpc_server_info * serverInfoP;
339
340     xmlrpc_env_init(&env);
341
342     serverInfoP = xmlrpc_server_info_new(&env, serverUrl);
343
344     if (!env.fault_occurred) {
345         xmlrpc_client_call_server_asynch_params(
346             serverInfoP, methodName, responseHandler, userData, paramArrayP);
347         
348         xmlrpc_server_info_free(serverInfoP);
349     }
350     if (env.fault_occurred)
351         (*responseHandler)(serverUrl, methodName, paramArrayP, userData,
352                            &env, NULL);
353     xmlrpc_env_clean(&env);
354 }
355
356
357
358 void 
359 xmlrpc_client_call_server_asynch(xmlrpc_server_info * const serverInfoP,
360                                  const char *         const methodName,
361                                  xmlrpc_response_handler    responseHandler,
362                                  void *               const userData,
363                                  const char *         const format,
364                                  ...) {
365
366     xmlrpc_env env;
367     xmlrpc_value * paramArrayP;
368     const char * suffix;
369     va_list args;
370     
371     xmlrpc_env_init(&env);
372
373     va_start(args, format);
374     xmlrpc_build_value_va(&env, format, args, &paramArrayP, &suffix);
375     va_end(args);
376
377     if (!env.fault_occurred) {
378         if (*suffix != '\0')
379             xmlrpc_faultf(&env, "Junk after the argument "
380                           "specifier: '%s'.  "
381                           "There must be exactly one arument.",
382                           suffix);
383         else
384             xmlrpc_client_call_server_asynch_params(
385                 serverInfoP, methodName, responseHandler, userData,
386                 paramArrayP);
387
388         xmlrpc_DECREF(paramArrayP);
389     }
390     if (env.fault_occurred)
391         (*responseHandler)(serverInfoP->_server_url, methodName, NULL,
392                            userData, &env, NULL);
393
394     xmlrpc_env_clean(&env);
395 }
396
397
398
399 void 
400 xmlrpc_client_event_loop_finish_asynch(void) {
401
402     XMLRPC_ASSERT(globalClientExists);
403     xmlrpc_client_event_loop_finish(globalClientP);
404 }
405
406
407
408 void 
409 xmlrpc_client_event_loop_finish_asynch_timeout(
410     unsigned long const milliseconds) {
411
412     XMLRPC_ASSERT(globalClientExists);
413     xmlrpc_client_event_loop_finish_timeout(globalClientP, milliseconds);
414 }