summaryrefslogtreecommitdiffstats
path: root/Utilities/cmxmlrpc/xmlrpc_client.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmxmlrpc/xmlrpc_client.c')
-rw-r--r--Utilities/cmxmlrpc/xmlrpc_client.c977
1 files changed, 0 insertions, 977 deletions
diff --git a/Utilities/cmxmlrpc/xmlrpc_client.c b/Utilities/cmxmlrpc/xmlrpc_client.c
deleted file mode 100644
index a5ad65c..0000000
--- a/Utilities/cmxmlrpc/xmlrpc_client.c
+++ /dev/null
@@ -1,977 +0,0 @@
-/* Copyright (C) 2001 by First Peer, Inc. All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions
-** are met:
-** 1. Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** 2. Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** 3. The name of the author may not be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-** SUCH DAMAGE. */
-
-#include "xmlrpc_config.h"
-
-#undef PACKAGE
-#undef VERSION
-
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-
-#include "bool.h"
-#include "mallocvar.h"
-#include "xmlrpc.h"
-#include "xmlrpc_int.h"
-#include "xmlrpc_client.h"
-#include "xmlrpc_client_int.h"
-/* transport_config.h defines XMLRPC_DEFAULT_TRANSPORT,
- MUST_BUILD_WININET_CLIENT, MUST_BUILD_CURL_CLIENT,
- MUST_BUILD_LIBWWW_CLIENT
-*/
-#include "transport_config.h"
-
-#if MUST_BUILD_WININET_CLIENT
-#include "xmlrpc_wininet_transport.h"
-#endif
-#if MUST_BUILD_CURL_CLIENT
-#include "xmlrpc_curl_transport.h"
-#endif
-#if MUST_BUILD_LIBWWW_CLIENT
-#include "xmlrpc_libwww_transport.h"
-#endif
-
-struct xmlrpc_client {
-/*----------------------------------------------------------------------------
- This represents a client object.
------------------------------------------------------------------------------*/
- struct clientTransport * transportP;
-};
-
-
-
-typedef struct call_info
-{
- /* These fields are used when performing asynchronous calls.
- ** The _asynch_data_holder contains server_url, method_name and
- ** param_array, so it's the only thing we need to free. */
- xmlrpc_value *_asynch_data_holder;
- char *server_url;
- char *method_name;
- xmlrpc_value *param_array;
- xmlrpc_response_handler callback;
- void *user_data;
-
- /* The serialized XML data passed to this call. We keep this around
- ** for use by our source_anchor field. */
- xmlrpc_mem_block *serialized_xml;
-} call_info;
-
-static bool clientInitialized = FALSE;
-
-/*=========================================================================
-** Initialization and Shutdown
-**=========================================================================
-*/
-
-static struct clientTransportOps clientTransportOps;
-
-static struct xmlrpc_client client;
- /* Some day, we need to make this dynamically allocated, so there can
- be more than one client per program and just generally to provide
- a cleaner interface.
- */
-
-extern void
-xmlrpc_client_init(int const flags,
- const char * const appname,
- const char * const appversion) {
-
- struct xmlrpc_clientparms clientparms;
-
- /* As our interface does not allow for failure, we just fail silently ! */
-
- xmlrpc_env env;
- xmlrpc_env_init(&env);
-
- clientparms.transport = XMLRPC_DEFAULT_TRANSPORT;
-
- xmlrpc_client_init2(&env, flags,
- appname, appversion,
- &clientparms, XMLRPC_CPSIZE(transport));
-
- xmlrpc_env_clean(&env);
-}
-
-
-
-const char *
-xmlrpc_client_get_default_transport(xmlrpc_env * const env ATTR_UNUSED) {
-
- return XMLRPC_DEFAULT_TRANSPORT;
-}
-
-
-
-static void
-setupTransport(xmlrpc_env * const envP,
- const char * const transportName) {
-
- if (FALSE) {
- }
-#if MUST_BUILD_WININET_CLIENT
- else if (strcmp(transportName, "wininet") == 0)
- clientTransportOps = xmlrpc_wininet_transport_ops;
-#endif
-#if MUST_BUILD_CURL_CLIENT
- else if (strcmp(transportName, "curl") == 0)
- clientTransportOps = xmlrpc_curl_transport_ops;
- else if (strcmp(transportName, "libcurl") == 0)
- clientTransportOps = xmlrpc_curl_transport_ops;
-#endif
-#if MUST_BUILD_LIBWWW_CLIENT
- else if (strcmp(transportName, "libwww") == 0)
- clientTransportOps = xmlrpc_libwww_transport_ops;
-#endif
- else
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Unrecognized XML transport name '%s'", transportName);
-}
-
-
-
-void
-xmlrpc_client_init2(xmlrpc_env * const envP,
- int const flags,
- const char * const appname,
- const char * const appversion,
- struct xmlrpc_clientparms * const clientparmsP,
- unsigned int const parm_size) {
-
- if (clientInitialized)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Xmlrpc-c client instance has already been initialized "
- "(need to call xmlrpc_client_cleanup() before you can "
- "reinitialize).");
- else {
- const char * transportName;
-
- if (parm_size < XMLRPC_CPSIZE(transport) ||
- clientparmsP->transport == NULL) {
- /* He didn't specify a transport. Use the default */
- transportName = xmlrpc_client_get_default_transport(envP);
- } else
- transportName = clientparmsP->transport;
-
- if (!envP->fault_occurred) {
- setupTransport(envP, transportName);
- if (!envP->fault_occurred) {
- clientTransportOps.create(envP, flags, appname, appversion,
- &client.transportP);
- if (!envP->fault_occurred)
- clientInitialized = TRUE;
- }
- }
- }
-}
-
-
-
-void
-xmlrpc_client_cleanup() {
-
- XMLRPC_ASSERT(clientInitialized);
-
- clientTransportOps.destroy(client.transportP);
-
- clientInitialized = FALSE;
-}
-
-
-
-static void
-call_info_free(call_info * const callInfoP) {
-
- /* Assume the worst.. That only parts of the call_info are valid. */
-
- XMLRPC_ASSERT_PTR_OK(callInfoP);
-
- /* If this has been allocated, we're responsible for destroying it. */
- if (callInfoP->_asynch_data_holder)
- xmlrpc_DECREF(callInfoP->_asynch_data_holder);
-
- /* Now we can blow away the XML data. */
- if (callInfoP->serialized_xml)
- xmlrpc_mem_block_free(callInfoP->serialized_xml);
-
- free(callInfoP);
-}
-
-
-
-static void
-call_info_new(xmlrpc_env * const envP,
- xmlrpc_server_info * const server,
- const char * const method_name,
- xmlrpc_value * const argP,
- call_info ** const callInfoPP) {
-/*----------------------------------------------------------------------------
- Create a call_info object. A call_info object represents an XML-RPC
- call.
------------------------------------------------------------------------------*/
- call_info * callInfoP;
-
- XMLRPC_ASSERT_PTR_OK(argP);
- XMLRPC_ASSERT_PTR_OK(callInfoPP);
-
- if (method_name == NULL)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "method name argument is NULL pointer");
- else if (server == NULL)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "server info argument is NULL pointer");
- else {
- MALLOCVAR(callInfoP);
- if (callInfoP == NULL)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for xmlrpc_call_info");
- else {
- xmlrpc_mem_block * callXmlP;
-
- /* Clear contents. */
- memset(callInfoP, 0, sizeof(*callInfoP));
-
- /* Make the XML for our call */
- callXmlP = XMLRPC_MEMBLOCK_NEW(char, envP, 0);
- if (!envP->fault_occurred) {
- xmlrpc_serialize_call(envP, callXmlP, method_name, argP);
- if (!envP->fault_occurred) {
- xmlrpc_traceXml("XML-RPC CALL",
- XMLRPC_MEMBLOCK_CONTENTS(char, callXmlP),
- (unsigned int)XMLRPC_MEMBLOCK_SIZE(char, callXmlP));
-
- callInfoP->serialized_xml = callXmlP;
-
- *callInfoPP = callInfoP;
- }
- if (envP->fault_occurred)
- XMLRPC_MEMBLOCK_FREE(char, callXmlP);
- }
- if (envP->fault_occurred)
- free(callInfoP);
- }
- }
-}
-
-
-
-static void
-clientCallServerParams(xmlrpc_env * const envP,
- struct clientTransport * const transportP,
- xmlrpc_server_info * const serverP,
- const char * const methodName,
- xmlrpc_value * const paramArrayP,
- xmlrpc_value ** const resultPP) {
-
- call_info * callInfoP;
-
- if (!clientInitialized)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Xmlrpc-c client instance has not been initialized "
- "(need to call xmlrpc_client_init2()).");
- else {
- call_info_new(envP, serverP, methodName, paramArrayP, &callInfoP);
- if (!envP->fault_occurred) {
- xmlrpc_mem_block * respXmlP;
-
- clientTransportOps.call(envP, transportP, serverP,
- callInfoP->serialized_xml, callInfoP,
- &respXmlP);
- if (!envP->fault_occurred) {
- xmlrpc_traceXml("XML-RPC RESPONSE",
- XMLRPC_MEMBLOCK_CONTENTS(char, respXmlP),
- (unsigned int)XMLRPC_MEMBLOCK_SIZE(char, respXmlP));
-
- *resultPP = xmlrpc_parse_response(
- envP,
- XMLRPC_MEMBLOCK_CONTENTS(char, respXmlP),
- XMLRPC_MEMBLOCK_SIZE(char, respXmlP));
- XMLRPC_MEMBLOCK_FREE(char, respXmlP);
- }
- call_info_free(callInfoP);
- }
- }
-}
-
-
-
-xmlrpc_value *
-xmlrpc_client_call_params(xmlrpc_env * const envP,
- const char * const serverUrl,
- const char * const methodName,
- xmlrpc_value * const paramArrayP) {
-
- xmlrpc_value *retval;
-
- XMLRPC_ASSERT_ENV_OK(envP);
- XMLRPC_ASSERT_PTR_OK(serverUrl);
-
- if (!clientInitialized)
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR,
- "Xmlrpc-c client instance has not been initialized "
- "(need to call xmlrpc_client_init2()).");
- else {
- xmlrpc_server_info * serverP;
-
- /* Build a server info object and make our call. */
- serverP = xmlrpc_server_info_new(envP, serverUrl);
- if (!envP->fault_occurred) {
- clientCallServerParams(envP, client.transportP, serverP,
- methodName, paramArrayP,
- &retval);
-
- xmlrpc_server_info_free(serverP);
- }
- }
-
- if (!envP->fault_occurred)
- XMLRPC_ASSERT_VALUE_OK(retval);
-
- return retval;
-}
-
-
-
-static xmlrpc_value *
-xmlrpc_client_call_va(xmlrpc_env * const envP,
- const char * const server_url,
- const char * const method_name,
- const char * const format,
- va_list args) {
-
- xmlrpc_value * argP;
- xmlrpc_value * retval = 0;
- xmlrpc_env argenv;
- const char * suffix;
-
- XMLRPC_ASSERT_ENV_OK(envP);
- XMLRPC_ASSERT_PTR_OK(format);
-
- /* Build our argument value. */
- xmlrpc_env_init(&argenv);
- xmlrpc_build_value_va(&argenv, format, args, &argP, &suffix);
- if (argenv.fault_occurred) {
- xmlrpc_env_set_fault_formatted(
- envP, argenv.fault_code, "Invalid RPC arguments. "
- "The format argument must indicate a single array, and the "
- "following arguments must correspond to that format argument. "
- "The failure is: %s",
- argenv.fault_string);
- xmlrpc_env_clean(&argenv);
- } else {
- XMLRPC_ASSERT_VALUE_OK(argP);
-
- if (*suffix != '\0')
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR, "Junk after the argument "
- "specifier: '%s'. There must be exactly one arument.",
- suffix);
- else {
- /* Perform the actual XML-RPC call. */
- retval = xmlrpc_client_call_params(
- envP, server_url, method_name, argP);
- if (!envP->fault_occurred)
- XMLRPC_ASSERT_VALUE_OK(retval);
- }
- xmlrpc_DECREF(argP);
- }
- return retval;
-}
-
-
-
-xmlrpc_value *
-xmlrpc_client_call(xmlrpc_env * const envP,
- const char * const server_url,
- const char * const method_name,
- const char * const format,
- ...) {
-
- xmlrpc_value * result;
- va_list args;
-
- va_start(args, format);
- result = xmlrpc_client_call_va(envP, server_url,
- method_name, format, args);
- va_end(args);
-
- return result;
-}
-
-
-
-xmlrpc_value *
-xmlrpc_client_call_server(xmlrpc_env * const envP,
- xmlrpc_server_info * const serverP,
- const char * const methodName,
- const char * const format,
- ...) {
-
- va_list args;
- xmlrpc_value * paramArrayP;
- xmlrpc_value * retval;
- const char * suffix;
-
- XMLRPC_ASSERT_ENV_OK(envP);
- XMLRPC_ASSERT_PTR_OK(format);
-
- /* Build our argument */
- va_start(args, format);
- xmlrpc_build_value_va(envP, format, args, &paramArrayP, &suffix);
- va_end(args);
-
- if (!envP->fault_occurred) {
- if (*suffix != '\0')
- xmlrpc_env_set_fault_formatted(
- envP, XMLRPC_INTERNAL_ERROR, "Junk after the argument "
- "specifier: '%s'. There must be exactly one arument.",
- suffix);
- else
- clientCallServerParams(envP, client.transportP, serverP,
- methodName, paramArrayP,
- &retval);
-
- xmlrpc_DECREF(paramArrayP);
- }
- return retval;
-}
-
-
-void
-xmlrpc_client_event_loop_finish_asynch(void) {
- XMLRPC_ASSERT(clientInitialized);
- clientTransportOps.finish_asynch(client.transportP, timeout_no, 0);
-}
-
-
-
-void
-xmlrpc_client_event_loop_finish_asynch_timeout(timeout_t const timeout) {
- XMLRPC_ASSERT(clientInitialized);
- clientTransportOps.finish_asynch(client.transportP, timeout_yes, timeout);
-}
-
-
-
-static void
-call_info_set_asynch_data(xmlrpc_env * const env,
- call_info * const info,
- const char * const server_url,
- const char * const method_name,
- xmlrpc_value * const argP,
- xmlrpc_response_handler callback,
- void * const user_data) {
-
- xmlrpc_value *holder;
-
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT_PTR_OK(info);
- XMLRPC_ASSERT(info->_asynch_data_holder == NULL);
- XMLRPC_ASSERT_PTR_OK(server_url);
- XMLRPC_ASSERT_PTR_OK(method_name);
- XMLRPC_ASSERT_VALUE_OK(argP);
-
- /* Install our callback and user_data.
- ** (We're not responsible for destroying the user_data.) */
- info->callback = callback;
- info->user_data = user_data;
-
- /* Build an XML-RPC data structure to hold our other data. This makes
- ** copies of server_url and method_name, and increments the reference
- ** to the argument *argP. */
- holder = xmlrpc_build_value(env, "(ssV)",
- server_url, method_name, argP);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Parse the newly-allocated structure into our public member variables.
- ** This doesn't make any new references, so we can dispose of the whole
- ** thing by DECREF'ing the one master reference. Nifty, huh? */
- xmlrpc_parse_value(env, holder, "(ssV)",
- &info->server_url,
- &info->method_name,
- &info->param_array);
- XMLRPC_FAIL_IF_FAULT(env);
-
- /* Hand over ownership of the holder to the call_info struct. */
- info->_asynch_data_holder = holder;
- holder = NULL;
-
- cleanup:
- if (env->fault_occurred) {
- if (holder)
- xmlrpc_DECREF(holder);
- }
-}
-
-/*=========================================================================
-** xmlrpc_server_info
-**=========================================================================
-*/
-
-xmlrpc_server_info *
-xmlrpc_server_info_new (xmlrpc_env * const env,
- const char * const server_url) {
-
- xmlrpc_server_info *server;
- char *url_copy;
-
- /* Error-handling preconditions. */
- url_copy = NULL;
-
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT_PTR_OK(server_url);
-
- /* Allocate our memory blocks. */
- server = (xmlrpc_server_info*) malloc(sizeof(xmlrpc_server_info));
- XMLRPC_FAIL_IF_NULL(server, env, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for xmlrpc_server_info");
- memset(server, 0, sizeof(xmlrpc_server_info));
- url_copy = (char*) malloc(strlen(server_url) + 1);
- XMLRPC_FAIL_IF_NULL(url_copy, env, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for server URL");
-
- /* Build our object. */
- strcpy(url_copy, server_url);
- server->_server_url = url_copy;
- server->_http_basic_auth = NULL;
-
- cleanup:
- if (env->fault_occurred) {
- if (url_copy)
- free(url_copy);
- if (server)
- free(server);
- return NULL;
- }
- return server;
-}
-
-xmlrpc_server_info * xmlrpc_server_info_copy(xmlrpc_env *env,
- xmlrpc_server_info *aserver)
-{
- xmlrpc_server_info *server;
- char *url_copy, *auth_copy;
-
- XMLRPC_ASSERT_ENV_OK(env);
- XMLRPC_ASSERT_PTR_OK(aserver);
-
- /* Error-handling preconditions. */
- url_copy = NULL;
- auth_copy = NULL;
-
- /* Allocate our memory blocks. */
- server = (xmlrpc_server_info*) malloc(sizeof(xmlrpc_server_info));
- XMLRPC_FAIL_IF_NULL(server, env, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for xmlrpc_server_info");
- url_copy = (char*) malloc(strlen(aserver->_server_url) + 1);
- XMLRPC_FAIL_IF_NULL(url_copy, env, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for server URL");
- auth_copy = (char*) malloc(strlen(aserver->_http_basic_auth) + 1);
- XMLRPC_FAIL_IF_NULL(auth_copy, env, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for authentication info");
-
- /* Build our object. */
- strcpy(url_copy, aserver->_server_url);
- server->_server_url = url_copy;
- strcpy(auth_copy, aserver->_http_basic_auth);
- server->_http_basic_auth = auth_copy;
-
- cleanup:
- if (env->fault_occurred) {
- if (url_copy)
- free(url_copy);
- if (auth_copy)
- free(auth_copy);
- if (server)
- free(server);
- return NULL;
- }
- return server;
-
-}
-
-void xmlrpc_server_info_free (xmlrpc_server_info *server)
-{
- XMLRPC_ASSERT_PTR_OK(server);
- XMLRPC_ASSERT(server->_server_url != XMLRPC_BAD_POINTER);
-
- if (server->_http_basic_auth)
- free(server->_http_basic_auth);
- free(server->_server_url);
- server->_server_url = XMLRPC_BAD_POINTER;
- free(server);
-}
-
-/*=========================================================================
-** xmlrpc_client_call_asynch
-**=========================================================================
-*/
-
-void
-xmlrpc_client_call_asynch(const char * const serverUrl,
- const char * const methodName,
- xmlrpc_response_handler callback,
- void * const userData,
- const char * const format,
- ...) {
-
- xmlrpc_env env;
- va_list args;
- xmlrpc_value * paramArrayP;
- const char * suffix;
-
- xmlrpc_env_init(&env);
-
- XMLRPC_ASSERT_PTR_OK(serverUrl);
- XMLRPC_ASSERT_PTR_OK(format);
-
- /* Build our argument array. */
- va_start(args, format);
- xmlrpc_build_value_va(&env, format, args, &paramArrayP, &suffix);
- va_end(args);
- if (env.fault_occurred) {
- /* Unfortunately, we have no way to return an error and the
- regular callback for a failed RPC is designed to have the
- parameter array passed to it. This was probably an oversight
- of the original asynch design, but now we have to be as
- backward compatible as possible, so we do this:
- */
- (*callback)(serverUrl, methodName, NULL, userData, &env, NULL);
- } else {
- if (*suffix != '\0')
- xmlrpc_env_set_fault_formatted(
- &env, XMLRPC_INTERNAL_ERROR, "Junk after the argument "
- "specifier: '%s'. There must be exactly one arument.",
- suffix);
- else {
- xmlrpc_server_info * serverP;
- serverP = xmlrpc_server_info_new(&env, serverUrl);
- if (!env.fault_occurred) {
- xmlrpc_client_call_server_asynch_params(
- serverP, methodName, callback, userData,
- paramArrayP);
- }
- xmlrpc_server_info_free(serverP);
- }
- if (env.fault_occurred)
- (*callback)(serverUrl, methodName, paramArrayP, userData,
- &env, NULL);
- xmlrpc_DECREF(paramArrayP);
- }
-
- xmlrpc_env_clean(&env);
-}
-
-
-
-void
-xmlrpc_client_call_asynch_params(const char * const serverUrl,
- const char * const methodName,
- xmlrpc_response_handler callback,
- void * const userData,
- xmlrpc_value * const paramArrayP) {
-
- xmlrpc_env env;
- xmlrpc_server_info *serverP;
-
- xmlrpc_env_init(&env);
-
- XMLRPC_ASSERT_PTR_OK(serverUrl);
-
- serverP = xmlrpc_server_info_new(&env, serverUrl);
- if (!env.fault_occurred) {
- xmlrpc_client_call_server_asynch_params(
- serverP, methodName, callback, userData, paramArrayP);
-
- xmlrpc_server_info_free(serverP);
- }
-
- if (env.fault_occurred)
- /* We have no way to return failure; we report the failure
- as it happened after we successfully started the RPC.
- */
- (*callback)(serverUrl, methodName, paramArrayP, userData,
- &env, NULL);
-
- xmlrpc_env_clean(&env);
-}
-
-
-
-void
-xmlrpc_client_call_server_asynch(xmlrpc_server_info * const serverP,
- const char * const methodName,
- xmlrpc_response_handler callback,
- void * const userData,
- const char * const format,
- ...) {
-
- xmlrpc_env env;
- va_list args;
- xmlrpc_value * paramArrayP;
- const char * suffix;
-
- xmlrpc_env_init(&env);
-
- XMLRPC_ASSERT_PTR_OK(format);
-
- /* Build our parameter array. */
- va_start(args, format);
- xmlrpc_build_value_va(&env, format, args, &paramArrayP, &suffix);
- va_end(args);
- if (env.fault_occurred) {
- /* Unfortunately, we have no way to return an error and the
- regular callback for a failed RPC is designed to have the
- parameter array passed to it. This was probably an oversight
- of the original asynch design, but now we have to be as
- backward compatible as possible, so we do this:
- */
- (*callback)(serverP->_server_url, methodName, NULL, userData,
- &env, NULL);
- } else {
- if (*suffix != '\0')
- xmlrpc_env_set_fault_formatted(
- &env, XMLRPC_INTERNAL_ERROR, "Junk after the argument "
- "specifier: '%s'. There must be exactly one arument.",
- suffix);
- else {
- xmlrpc_client_call_server_asynch_params(
- serverP, methodName, callback, userData, paramArrayP);
- }
- xmlrpc_DECREF(paramArrayP);
- }
-
- if (env.fault_occurred)
- (*callback)(serverP->_server_url, methodName, paramArrayP, userData,
- &env, NULL);
-
- xmlrpc_env_clean(&env);
-}
-
-
-
-static void
-asynchComplete(call_info * const callInfoP,
- xmlrpc_mem_block * const responseXmlP,
- xmlrpc_env const transportEnv) {
-/*----------------------------------------------------------------------------
- Complete an asynchronous XML-RPC call request.
-
- This includes calling the user's RPC completion routine.
-
- 'transportEnv' describes the an error that the transport
- encountered in processing the call. If the transport successfully
- sent the call to the server and processed the response but the
- server failed the call, 'transportEnv' indicates no error, and the
- response in *callInfoP might very well indicate that the server
- failed the request.
------------------------------------------------------------------------------*/
- xmlrpc_env env;
- xmlrpc_value * responseP = 0;
-
- xmlrpc_env_init(&env);
-
- if (transportEnv.fault_occurred)
- xmlrpc_env_set_fault_formatted(
- &env, transportEnv.fault_code,
- "Client transport failed to execute the RPC. %s",
- transportEnv.fault_string);
-
- if (!env.fault_occurred)
- responseP = xmlrpc_parse_response(
- &env,
- XMLRPC_MEMBLOCK_CONTENTS(char, responseXmlP),
- XMLRPC_MEMBLOCK_SIZE(char, responseXmlP));
-
- /* Call the user's callback function with the result */
- (*callInfoP->callback)(callInfoP->server_url,
- callInfoP->method_name,
- callInfoP->param_array,
- callInfoP->user_data, &env, responseP);
-
- if (!env.fault_occurred)
- xmlrpc_DECREF(responseP);
-
- call_info_free(callInfoP);
-
- xmlrpc_env_clean(&env);
-}
-
-
-
-static void
-sendRequest(xmlrpc_env * const envP,
- struct clientTransport * const transportP,
- xmlrpc_server_info * const serverP,
- const char * const methodName,
- xmlrpc_response_handler responseHandler,
- void * const userData,
- xmlrpc_value * const argP) {
-
- call_info * callInfoP;
-
- call_info_new(envP, serverP, methodName, argP, &callInfoP);
- if (!envP->fault_occurred) {
- call_info_set_asynch_data(envP, callInfoP,
- serverP->_server_url, methodName,
- argP, responseHandler, userData);
- if (!envP->fault_occurred)
- clientTransportOps.send_request(
- envP, transportP, serverP, callInfoP->serialized_xml,
- &asynchComplete, callInfoP);
-
- if (envP->fault_occurred)
- call_info_free(callInfoP);
- else {
- /* asynchComplete() will free *callInfoP */
- }
- }
- if (envP->fault_occurred) {
- /* Transport did not start the call. Report the call complete
- (with error) now.
- */
- (*responseHandler)(serverP->_server_url, methodName, argP, userData,
- envP, NULL);
- } else {
- /* The transport will call *responseHandler() when it has completed
- the call
- */
- }
-}
-
-
-
-void
-xmlrpc_client_call_server_asynch_params(
- xmlrpc_server_info * const serverP,
- const char * const methodName,
- xmlrpc_response_handler responseHandler,
- void * const userData,
- xmlrpc_value * const argP) {
- xmlrpc_env env;
-
- xmlrpc_env_init(&env);
-
- XMLRPC_ASSERT_PTR_OK(serverP);
- XMLRPC_ASSERT_PTR_OK(methodName);
- XMLRPC_ASSERT_PTR_OK(responseHandler);
- XMLRPC_ASSERT_VALUE_OK(argP);
-
- if (!clientInitialized)
- xmlrpc_env_set_fault_formatted(
- &env, XMLRPC_INTERNAL_ERROR,
- "Xmlrpc-c client instance has not been initialized "
- "(need to call xmlrpc_client_init2()).");
- else
- sendRequest(&env, client.transportP, serverP,
- methodName, responseHandler, userData,
- argP);
-
- xmlrpc_env_clean(&env);
-}
-
-
-
-void
-xmlrpc_server_info_set_basic_auth(xmlrpc_env * const envP,
- xmlrpc_server_info * const serverP,
- const char * const username,
- const char * const password) {
-
- size_t username_len, password_len, raw_token_len;
- char *raw_token;
- xmlrpc_mem_block *token;
- char *token_data, *auth_type, *auth_header;
- size_t token_len, auth_type_len, auth_header_len;
-
- /* Error-handling preconditions. */
- token = NULL;
- auth_header = NULL;
-
- XMLRPC_ASSERT_ENV_OK(envP);
- XMLRPC_ASSERT_PTR_OK(serverP);
- XMLRPC_ASSERT_PTR_OK(username);
- XMLRPC_ASSERT_PTR_OK(password);
-
- /* Calculate some lengths. */
- username_len = strlen(username);
- password_len = strlen(password);
- raw_token_len = username_len + password_len + 1;
-
- /* Build a raw token of the form 'username:password'. */
- raw_token = (char*) malloc(raw_token_len + 1);
- XMLRPC_FAIL_IF_NULL(raw_token, envP, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for auth token");
- strcpy(raw_token, username);
- raw_token[username_len] = ':';
- strcpy(&raw_token[username_len + 1], password);
-
- /* Encode our raw token using Base64. */
- token = xmlrpc_base64_encode_without_newlines(envP,
- (unsigned char*) raw_token,
- raw_token_len);
- XMLRPC_FAIL_IF_FAULT(envP);
- token_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, token);
- token_len = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, token);
-
- /* Build our actual header value. (I hate string processing in C.) */
- auth_type = "Basic ";
- auth_type_len = strlen(auth_type);
- auth_header_len = auth_type_len + token_len;
- auth_header = (char*) malloc(auth_header_len + 1);
- XMLRPC_FAIL_IF_NULL(auth_header, envP, XMLRPC_INTERNAL_ERROR,
- "Couldn't allocate memory for auth header");
- memcpy(auth_header, auth_type, auth_type_len);
- memcpy(&auth_header[auth_type_len], token_data, token_len);
- auth_header[auth_header_len] = '\0';
-
- /* Clean up any pre-existing authentication information, and install
- ** the new value. */
- if (serverP->_http_basic_auth)
- free(serverP->_http_basic_auth);
- serverP->_http_basic_auth = auth_header;
-
- cleanup:
- if (raw_token)
- free(raw_token);
- if (token)
- xmlrpc_mem_block_free(token);
- if (envP->fault_occurred) {
- if (auth_header)
- free(auth_header);
- }
-}
-