mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-08-13 17:38:59 +00:00
add xmlrpc-c 1.03.14 to in tree libs
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3772 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
1
libs/xmlrpc-c/src/cpp/.cvsignore
Normal file
1
libs/xmlrpc-c/src/cpp/.cvsignore
Normal file
@@ -0,0 +1 @@
|
||||
cpptest
|
177
libs/xmlrpc-c/src/cpp/Makefile
Normal file
177
libs/xmlrpc-c/src/cpp/Makefile
Normal file
@@ -0,0 +1,177 @@
|
||||
ifeq ($(SRCDIR)x,x)
|
||||
SRCDIR = $(CURDIR)/../..
|
||||
endif
|
||||
SUBDIR = src/cpp
|
||||
BUILDDIR = $(SRCDIR)
|
||||
VPATH = .:$(SRCDIR)
|
||||
|
||||
include $(BUILDDIR)/Makefile.config
|
||||
|
||||
default: all
|
||||
|
||||
WININET_TRANSPORT_DIR = $(SRCDIR)/lib/wininet_transport
|
||||
CURL_TRANSPORT_DIR = $(SRCDIR)/lib/curl_transport
|
||||
LIBWWW_TRANSPORT_DIR = $(SRCDIR)/lib/libwww_transport
|
||||
|
||||
ifeq ($(ENABLE_LIBXML2_BACKEND),yes)
|
||||
LIBXML_INCLUDES = $(LIBXML2_CFLAGS)
|
||||
LIBXML = $(LIBXML2_LIBS)
|
||||
else
|
||||
LIBXML_INCLUDES = -I$(SRCDIR)/lib/expat/xmlparse
|
||||
LIBXML = $(BUILDDIR)/lib/expat/xmlparse/libxmlrpc_xmlparse.la \
|
||||
$(BUILDDIR)/lib/expat/xmltok/libxmlrpc_xmltok.la
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_LIBXML2),yes)
|
||||
XMLRPC_XML_PARSER = xmlrpc_libxml2.lo
|
||||
else
|
||||
XMLRPC_XML_PARSER = xmlrpc_expat.lo
|
||||
endif
|
||||
|
||||
LIBXMLRPC = $(BUILDDIR)/src/libxmlrpc.la
|
||||
LIBXMLRPC_SERVER = $(BUILDDIR)/src/libxmlrpc_server.la
|
||||
LIBXMLRPC_CLIENT = $(BUILDDIR)/src/libxmlrpc_client.la
|
||||
|
||||
LIBXMLRPCPP_OBJS = girmem.o value.o fault.o outcome.o param_list.o xml.o
|
||||
LIBXMLRPC_SERVERPP_OBJS = registry.o
|
||||
LIBXMLRPC_SERVER_ABYSSPP_OBJS = server_abyss.o
|
||||
LIBXMLRPC_CLIENTPP_OBJS = client.o client_simple.o
|
||||
|
||||
$(LIBXMLRPC_CLIENTPP_OBJS): $(BUILDDIR)/transport_config.h
|
||||
|
||||
TRANSPORT_OBJS =
|
||||
ifeq ($(MUST_BUILD_WININET_CLIENT),yes)
|
||||
TRANSPORT_OBJS += $(WININET_TRANSPORT_DIR)/xmlrpc_wininet_transport.lo
|
||||
endif
|
||||
ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
|
||||
TRANSPORT_OBJS += $(CURL_TRANSPORT_DIR)/xmlrpc_curl_transport.lo
|
||||
endif
|
||||
ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
|
||||
TRANSPORT_OBJS += $(LIBWWW_TRANSPORT_DIR)/xmlrpc_libwww_transport.lo
|
||||
endif
|
||||
|
||||
TRANSPORT_INCLUDES = \
|
||||
-I$(WININET_TRANSPORT_DIR) \
|
||||
-I$(CURL_TRANSPORT_DIR) \
|
||||
-I$(LIBWWW_TRANSPORT_DIR) \
|
||||
|
||||
BASIC_INCLUDES = -I$(SRCDIR)/include -I$(BUILDDIR) -I$(SRCDIR) \
|
||||
-I$(SRCDIR)/lib/util/include
|
||||
|
||||
# We always statically-link our C++ code because it's tiny, and C++ is
|
||||
# no good at shared libraries, anyway. It's actually getting bigger,
|
||||
# but since I'm determined not to expand the use of libtool (because
|
||||
# it obfuscates the build process), I haven't figured out yet how to
|
||||
# get the shared libraries to build for all the platforms.
|
||||
|
||||
# libxmlrpc_cpp.a is the legacy C++ wrapper library. The others are the
|
||||
# more elaborate replacements.
|
||||
|
||||
TARGET_LIBRARIES = \
|
||||
libxmlrpc_cpp.a \
|
||||
libxmlrpc++.a \
|
||||
libxmlrpc_server++.a \
|
||||
libxmlrpc_server_abyss++.a \
|
||||
libxmlrpc_client++.a \
|
||||
|
||||
TARGET_PROGS = cpptest
|
||||
|
||||
all: $(TARGET_LIBRARIES)
|
||||
|
||||
ifeq ($(MUST_BUILD_CURL_CLIENT),yes)
|
||||
LDFLAGS += $(shell curl-config --libs) -lpthread
|
||||
endif
|
||||
ifeq ($(MUST_BUILD_LIBWWW_CLIENT),yes)
|
||||
LDFLAGS += $(shell libwww-config --libs)
|
||||
endif
|
||||
|
||||
LDFLAGS += $(LADD)
|
||||
|
||||
cpptest:%:%.o libxmlrpc_server_abyss++.a libxmlrpc_server++.a \
|
||||
libxmlrpc_client++.a libxmlrpc++.a libxmlrpc_cpp.a \
|
||||
$(LIBXMLRPC) $(LIBXMLRPC_SERVER) $(LIBXMLRPC_CLIENT) $(LIBXML)
|
||||
$(LIBTOOL) --mode=link $(CXXLD) -o $@ $(LDFLAGS) $^
|
||||
|
||||
LIBLDFLAGS = $(LADD)
|
||||
|
||||
libxmlrpc_cpp.a: XmlRpcCpp.o
|
||||
-rm -f $@
|
||||
$(AR) cru $@ $^
|
||||
$(RANLIB) $@
|
||||
|
||||
libxmlrpc++.a: $(LIBXMLRPCPP_OBJS)
|
||||
-rm -f $@
|
||||
$(AR) cru $@ $^
|
||||
$(RANLIB) $@
|
||||
|
||||
libxmlrpc_server++.a: $(LIBXMLRPC_SERVERPP_OBJS)
|
||||
-rm -f $@
|
||||
$(AR) cru $@ $^
|
||||
$(RANLIB) $@
|
||||
|
||||
libxmlrpc_server_abyss++.a: $(LIBXMLRPC_SERVER_ABYSSPP_OBJS)
|
||||
-rm -f $@
|
||||
$(AR) cru $@ $^
|
||||
$(RANLIB) $@
|
||||
|
||||
libxmlrpc_client++.a: $(LIBXMLRPC_CLIENTPP_OBJS)
|
||||
-rm -f $@
|
||||
$(AR) cru $@ $^
|
||||
$(RANLIB) $@
|
||||
|
||||
CXXFLAGS = $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
|
||||
|
||||
cpptest.o:%.o:%.cpp
|
||||
$(CXX) -c $(BASIC_INCLUDES) $(CXXFLAGS) $<
|
||||
|
||||
XmlRpcCpp.o:%.o:%.cpp
|
||||
$(CXX) -c $(BASIC_INCLUDES) $(CXXFLAGS) $<
|
||||
|
||||
$(LIBXMLRPCPP_OBJS):%.o:%.cpp
|
||||
$(CXX) -c $(BASIC_INCLUDES) $(CXXFLAGS) $<
|
||||
|
||||
SERVER_INCLUDES = $(BASIC_INCLUDES) $(LIBXML_INCLUDES)
|
||||
|
||||
$(LIBXMLRPC_SERVERPP_OBJS):%.o:%.cpp
|
||||
$(CXX) -c $(SERVER_INCLUDES) $(CXXFLAGS) $<
|
||||
|
||||
SERVER_ABYSS_INCLUDES = $(SERVER_INCLUDES) -I$(SRCDIR)/lib/abyss/src
|
||||
|
||||
$(LIBXMLRPC_SERVER_ABYSSPP_OBJS):%.o:%.cpp
|
||||
$(CXX) -c $(SERVER_ABYSS_INCLUDES) $(CXXFLAGS) $<
|
||||
|
||||
CLIENT_INCLUDES = $(BASIC_INCLUDES) $(LIBXML_INCLUDES) $(TRANSPORT_INCLUDES)
|
||||
|
||||
$(LIBXMLRPC_CLIENTPP_OBJS):%.o:%.cpp
|
||||
$(CXX) -c $(CLIENT_INCLUDES) $(CXXFLAGS) $<
|
||||
|
||||
|
||||
|
||||
LIBRARIES_TO_INSTALL = $(TARGET_LIBRARIES)
|
||||
|
||||
check: cpptest
|
||||
for tst in $^; do \
|
||||
./$$tst; \
|
||||
done;
|
||||
|
||||
.PHONY: install
|
||||
install: install-common
|
||||
|
||||
.PHONY: clean clean-local distclean
|
||||
clean: clean-common clean-local
|
||||
clean-local:
|
||||
rm -f $(TARGET_PROGS)
|
||||
|
||||
distclean: clean distclean-common
|
||||
|
||||
# INCLUDES and DEP_SOURCES are used by dep-common target
|
||||
INCLUDES = $(BASIC_INCLUDES) $(CLIENT_INCLUDES) $(LIBXML_INCLUDES) \
|
||||
$(SERVER_INCLUDES) $(SERVER_ABYSS_INCLUDES) $(TRANSPORT_INCLUDES)
|
||||
DEP_SOURCES = *.cpp
|
||||
|
||||
.PHONY: dep
|
||||
dep: $(BUILDDIR)/transport_config.h dep-common
|
||||
|
||||
include $(SRCDIR)/Makefile.common
|
||||
|
||||
include Makefile.depend
|
0
libs/xmlrpc-c/src/cpp/Makefile.depend
Normal file
0
libs/xmlrpc-c/src/cpp/Makefile.depend
Normal file
393
libs/xmlrpc-c/src/cpp/XmlRpcCpp.cpp
Normal file
393
libs/xmlrpc-c/src/cpp/XmlRpcCpp.cpp
Normal file
@@ -0,0 +1,393 @@
|
||||
// Copyright (C) 2001 by Eric Kidd. 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 <string>
|
||||
#include "xmlrpc-c/oldcppwrapper.hpp"
|
||||
|
||||
using std::string;
|
||||
|
||||
//=========================================================================
|
||||
// XmlRpcFault Methods
|
||||
//=========================================================================
|
||||
|
||||
XmlRpcFault::XmlRpcFault (const XmlRpcFault &fault) {
|
||||
xmlrpc_env_init(&mFault);
|
||||
xmlrpc_env_set_fault(&mFault,
|
||||
fault.mFault.fault_code,
|
||||
fault.mFault.fault_string);
|
||||
}
|
||||
|
||||
XmlRpcFault::XmlRpcFault (const int faultCode, const string faultString) {
|
||||
xmlrpc_env_init(&mFault);
|
||||
xmlrpc_env_set_fault(&mFault, faultCode,
|
||||
const_cast<char*>(faultString.c_str()));
|
||||
}
|
||||
|
||||
XmlRpcFault::XmlRpcFault (const xmlrpc_env *env) {
|
||||
if (!env->fault_string)
|
||||
throw XmlRpcFault(XMLRPC_INTERNAL_ERROR,
|
||||
"Tried to create empty fault");
|
||||
xmlrpc_env_init(&mFault);
|
||||
xmlrpc_env_set_fault(&mFault, env->fault_code,
|
||||
const_cast<char*>(env->fault_string));
|
||||
}
|
||||
|
||||
XmlRpcFault::~XmlRpcFault (void) {
|
||||
xmlrpc_env_clean(&mFault);
|
||||
}
|
||||
|
||||
string XmlRpcFault::getFaultString (void) const {
|
||||
XMLRPC_ASSERT(mFault.fault_occurred);
|
||||
return string(mFault.fault_string);
|
||||
}
|
||||
|
||||
|
||||
//=========================================================================
|
||||
// XmlRpcEnv Methods
|
||||
//=========================================================================
|
||||
|
||||
XmlRpcEnv::XmlRpcEnv (const XmlRpcEnv &env) {
|
||||
xmlrpc_env_init(&mEnv);
|
||||
if (env.hasFaultOccurred())
|
||||
xmlrpc_env_set_fault(&mEnv,
|
||||
env.mEnv.fault_code,
|
||||
env.mEnv.fault_string);
|
||||
}
|
||||
|
||||
XmlRpcFault XmlRpcEnv::getFault (void) const {
|
||||
return XmlRpcFault(&mEnv);
|
||||
}
|
||||
|
||||
void XmlRpcEnv::throwMe (void) const {
|
||||
throw XmlRpcFault(&mEnv);
|
||||
}
|
||||
|
||||
|
||||
//=========================================================================
|
||||
// XmlRpcValue Methods
|
||||
//=========================================================================
|
||||
|
||||
// If the user doesn't tell us what kind of value to create, use
|
||||
// a false boolean value as the default.
|
||||
XmlRpcValue::XmlRpcValue (void) {
|
||||
XmlRpcEnv env;
|
||||
mValue = xmlrpc_build_value(env, "b", (xmlrpc_bool) 0);
|
||||
env.throwIfFaultOccurred();
|
||||
}
|
||||
|
||||
XmlRpcValue XmlRpcValue::makeInt (const XmlRpcValue::int32 i) {
|
||||
XmlRpcEnv env;
|
||||
xmlrpc_value *value = xmlrpc_build_value(env, "i", i);
|
||||
env.throwIfFaultOccurred();
|
||||
return XmlRpcValue(value, CONSUME_REFERENCE);
|
||||
}
|
||||
|
||||
XmlRpcValue XmlRpcValue::makeBool (const bool b) {
|
||||
XmlRpcEnv env;
|
||||
xmlrpc_value *value = xmlrpc_build_value(env, "b", (xmlrpc_bool) b);
|
||||
env.throwIfFaultOccurred();
|
||||
return XmlRpcValue(value, CONSUME_REFERENCE);
|
||||
}
|
||||
|
||||
XmlRpcValue XmlRpcValue::makeDouble (const double d) {
|
||||
XmlRpcEnv env;
|
||||
xmlrpc_value *value = xmlrpc_build_value(env, "d", d);
|
||||
env.throwIfFaultOccurred();
|
||||
return XmlRpcValue(value, CONSUME_REFERENCE);
|
||||
}
|
||||
|
||||
XmlRpcValue XmlRpcValue::makeDateTime (const string& dateTime) {
|
||||
XmlRpcEnv env;
|
||||
xmlrpc_value *value;
|
||||
const char *data = dateTime.c_str(); // Make sure we're not using wchar_t.
|
||||
value = xmlrpc_build_value(env, "8", data);
|
||||
env.throwIfFaultOccurred();
|
||||
return XmlRpcValue(value, CONSUME_REFERENCE);
|
||||
}
|
||||
|
||||
XmlRpcValue XmlRpcValue::makeString (const string& str) {
|
||||
XmlRpcEnv env;
|
||||
const char *data = str.data(); // Make sure we're not using wchar_t.
|
||||
size_t size = str.size();
|
||||
xmlrpc_value *value = xmlrpc_build_value(env, "s#", data, size);
|
||||
env.throwIfFaultOccurred();
|
||||
return XmlRpcValue(value, CONSUME_REFERENCE);
|
||||
}
|
||||
|
||||
XmlRpcValue XmlRpcValue::makeString (const char *const str) {
|
||||
XmlRpcEnv env;
|
||||
xmlrpc_value *value = xmlrpc_build_value(env, "s", str);
|
||||
env.throwIfFaultOccurred();
|
||||
return XmlRpcValue(value, CONSUME_REFERENCE);
|
||||
}
|
||||
|
||||
XmlRpcValue XmlRpcValue::makeString (const char *const str, size_t len) {
|
||||
XmlRpcEnv env;
|
||||
xmlrpc_value *value = xmlrpc_build_value(env, "s#", str, len);
|
||||
env.throwIfFaultOccurred();
|
||||
return XmlRpcValue(value, CONSUME_REFERENCE);
|
||||
}
|
||||
|
||||
XmlRpcValue XmlRpcValue::makeArray (void) {
|
||||
XmlRpcEnv env;
|
||||
xmlrpc_value *value = xmlrpc_build_value(env, "()");
|
||||
env.throwIfFaultOccurred();
|
||||
return XmlRpcValue(value, CONSUME_REFERENCE);
|
||||
}
|
||||
|
||||
XmlRpcValue XmlRpcValue::makeStruct (void) {
|
||||
XmlRpcEnv env;
|
||||
xmlrpc_value *value = xmlrpc_struct_new(env);
|
||||
env.throwIfFaultOccurred();
|
||||
return XmlRpcValue(value, CONSUME_REFERENCE);
|
||||
}
|
||||
|
||||
XmlRpcValue XmlRpcValue::makeBase64 (const unsigned char *const data,
|
||||
size_t len)
|
||||
{
|
||||
XmlRpcEnv env;
|
||||
xmlrpc_value *value = xmlrpc_build_value(env, "6", data, len);
|
||||
env.throwIfFaultOccurred();
|
||||
return XmlRpcValue(value, CONSUME_REFERENCE);
|
||||
}
|
||||
|
||||
XmlRpcValue::int32 XmlRpcValue::getInt (void) const {
|
||||
XmlRpcEnv env;
|
||||
XmlRpcValue::int32 result;
|
||||
xmlrpc_parse_value(env, mValue, "i", &result);
|
||||
env.throwIfFaultOccurred();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool XmlRpcValue::getBool (void) const {
|
||||
XmlRpcEnv env;
|
||||
xmlrpc_bool result;
|
||||
xmlrpc_parse_value(env, mValue, "b", &result);
|
||||
env.throwIfFaultOccurred();
|
||||
return result;
|
||||
}
|
||||
|
||||
double XmlRpcValue::getDouble (void) const {
|
||||
XmlRpcEnv env;
|
||||
double result;
|
||||
xmlrpc_parse_value(env, mValue, "d", &result);
|
||||
env.throwIfFaultOccurred();
|
||||
return result;
|
||||
}
|
||||
|
||||
string XmlRpcValue::getRawDateTime (void) const {
|
||||
XmlRpcEnv env;
|
||||
char *result;
|
||||
xmlrpc_parse_value(env, mValue, "8", &result);
|
||||
env.throwIfFaultOccurred();
|
||||
return string(result);
|
||||
}
|
||||
|
||||
string XmlRpcValue::getString (void) const {
|
||||
XmlRpcEnv env;
|
||||
char *result;
|
||||
size_t result_len;
|
||||
xmlrpc_parse_value(env, mValue, "s#", &result, &result_len);
|
||||
env.throwIfFaultOccurred();
|
||||
return string(result, result_len);
|
||||
|
||||
}
|
||||
|
||||
XmlRpcValue XmlRpcValue::getArray (void) const {
|
||||
XmlRpcEnv env;
|
||||
xmlrpc_value *result;
|
||||
xmlrpc_parse_value(env, mValue, "A", &result);
|
||||
env.throwIfFaultOccurred();
|
||||
return XmlRpcValue(result);
|
||||
}
|
||||
|
||||
XmlRpcValue XmlRpcValue::getStruct (void) const {
|
||||
XmlRpcEnv env;
|
||||
xmlrpc_value *result;
|
||||
xmlrpc_parse_value(env, mValue, "S", &result);
|
||||
env.throwIfFaultOccurred();
|
||||
return XmlRpcValue(result);
|
||||
}
|
||||
|
||||
void XmlRpcValue::getBase64 (const unsigned char *& out_data,
|
||||
size_t& out_len) const
|
||||
{
|
||||
XmlRpcEnv env;
|
||||
xmlrpc_parse_value(env, mValue, "6", &out_data, &out_len);
|
||||
env.throwIfFaultOccurred();
|
||||
}
|
||||
|
||||
size_t XmlRpcValue::arraySize (void) const {
|
||||
XmlRpcEnv env;
|
||||
size_t result = xmlrpc_array_size(env, mValue);
|
||||
env.throwIfFaultOccurred();
|
||||
return result;
|
||||
}
|
||||
|
||||
void XmlRpcValue::arrayAppendItem (const XmlRpcValue& value) {
|
||||
XmlRpcEnv env;
|
||||
xmlrpc_array_append_item(env, mValue, value.borrowReference());
|
||||
env.throwIfFaultOccurred();
|
||||
}
|
||||
|
||||
XmlRpcValue XmlRpcValue::arrayGetItem (int index) const {
|
||||
XmlRpcEnv env;
|
||||
xmlrpc_value *result = xmlrpc_array_get_item(env, mValue, index);
|
||||
env.throwIfFaultOccurred();
|
||||
return XmlRpcValue(result);
|
||||
}
|
||||
|
||||
size_t XmlRpcValue::structSize (void) const {
|
||||
XmlRpcEnv env;
|
||||
size_t result = xmlrpc_struct_size(env, mValue);
|
||||
env.throwIfFaultOccurred();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool XmlRpcValue::structHasKey (const string& key) const {
|
||||
XmlRpcEnv env;
|
||||
const char *keystr = key.data();
|
||||
size_t keylen = key.size();
|
||||
bool result = xmlrpc_struct_has_key_n(env, mValue,
|
||||
const_cast<char*>(keystr), keylen);
|
||||
env.throwIfFaultOccurred();
|
||||
return result;
|
||||
}
|
||||
|
||||
XmlRpcValue XmlRpcValue::structGetValue (const string& key) const {
|
||||
XmlRpcEnv env;
|
||||
const char *keystr = key.data();
|
||||
size_t keylen = key.size();
|
||||
xmlrpc_value *result =
|
||||
xmlrpc_struct_get_value_n(env, mValue,
|
||||
const_cast<char*>(keystr), keylen);
|
||||
env.throwIfFaultOccurred();
|
||||
return XmlRpcValue(result);
|
||||
}
|
||||
|
||||
void XmlRpcValue::structSetValue (const string& key, const XmlRpcValue& value)
|
||||
{
|
||||
XmlRpcEnv env;
|
||||
const char *keystr = key.data();
|
||||
size_t keylen = key.size();
|
||||
xmlrpc_struct_set_value_n(env, mValue, (char*) keystr, keylen,
|
||||
value.borrowReference());
|
||||
env.throwIfFaultOccurred();
|
||||
}
|
||||
|
||||
void XmlRpcValue::structGetKeyAndValue (const int index,
|
||||
string& out_key,
|
||||
XmlRpcValue& out_value) const
|
||||
{
|
||||
XmlRpcEnv env;
|
||||
|
||||
xmlrpc_value *key, *value;
|
||||
xmlrpc_struct_get_key_and_value(env, mValue, index, &key, &value);
|
||||
env.throwIfFaultOccurred();
|
||||
|
||||
out_key = XmlRpcValue(key).getString();
|
||||
out_value = XmlRpcValue(value);
|
||||
}
|
||||
|
||||
XmlRpcGenSrv& XmlRpcGenSrv::addMethod (const string& name,
|
||||
xmlrpc_method method,
|
||||
void *data)
|
||||
{
|
||||
XmlRpcEnv env;
|
||||
|
||||
xmlrpc_registry_add_method (env, mRegistry, NULL,
|
||||
name.c_str (),
|
||||
method, data);
|
||||
|
||||
env.throwIfFaultOccurred ();
|
||||
return (*this);
|
||||
}
|
||||
|
||||
XmlRpcGenSrv& XmlRpcGenSrv::addMethod (const string& name,
|
||||
xmlrpc_method method,
|
||||
void* data,
|
||||
const string& signature,
|
||||
const string& help)
|
||||
{
|
||||
XmlRpcEnv env;
|
||||
|
||||
xmlrpc_registry_add_method_w_doc (env, mRegistry, NULL,
|
||||
name.c_str (),
|
||||
method, data,
|
||||
signature.c_str (),
|
||||
help.c_str ());
|
||||
|
||||
env.throwIfFaultOccurred ();
|
||||
return (*this);
|
||||
}
|
||||
|
||||
xmlrpc_mem_block* XmlRpcGenSrv::alloc (XmlRpcEnv& env, const string& body) const
|
||||
{
|
||||
xmlrpc_mem_block* result = NULL;
|
||||
char* contents;
|
||||
|
||||
result = xmlrpc_mem_block_new (env, body.length ());
|
||||
env.throwIfFaultOccurred ();
|
||||
|
||||
contents = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, result);
|
||||
|
||||
memcpy (contents, body.c_str (), body.length ());
|
||||
return result;
|
||||
}
|
||||
|
||||
string XmlRpcGenSrv::handle (const string& body) const
|
||||
{
|
||||
XmlRpcEnv env;
|
||||
string result;
|
||||
xmlrpc_mem_block* input = NULL, * output = NULL;
|
||||
char* input_data, * output_data;
|
||||
size_t input_size, output_size;
|
||||
|
||||
if (body.length () > xmlrpc_limit_get (XMLRPC_XML_SIZE_LIMIT_ID))
|
||||
throw XmlRpcFault (XMLRPC_LIMIT_EXCEEDED_ERROR, "XML-RPC request too large");
|
||||
|
||||
input = alloc (env, body);
|
||||
input_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, input);
|
||||
input_size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, input);
|
||||
|
||||
output = xmlrpc_registry_process_call (env, mRegistry, NULL,
|
||||
input_data, input_size);
|
||||
|
||||
if (output)
|
||||
{
|
||||
output_data = XMLRPC_TYPED_MEM_BLOCK_CONTENTS(char, output);
|
||||
output_size = XMLRPC_TYPED_MEM_BLOCK_SIZE(char, output);
|
||||
|
||||
result.assign (output_data, output_size);
|
||||
xmlrpc_mem_block_free (output);
|
||||
}
|
||||
|
||||
xmlrpc_mem_block_free (input);
|
||||
if (!result.length ())
|
||||
throw XmlRpcFault (env);
|
||||
|
||||
return result;
|
||||
}
|
851
libs/xmlrpc-c/src/cpp/client.cpp
Normal file
851
libs/xmlrpc-c/src/cpp/client.cpp
Normal file
@@ -0,0 +1,851 @@
|
||||
/*=============================================================================
|
||||
client.cpp
|
||||
===============================================================================
|
||||
This is the C++ XML-RPC client library for Xmlrpc-c.
|
||||
|
||||
Note that unlike most of Xmlprc-c's C++ API, this is _not_ based on the
|
||||
C client library. This code is independent of the C client library, and
|
||||
is based directly on the client XML transport libraries (with a little
|
||||
help from internal C utility libraries).
|
||||
=============================================================================*/
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
#include "xmlrpc-c/girerr.hpp"
|
||||
using girerr::error;
|
||||
#include "xmlrpc-c/girmem.hpp"
|
||||
using girmem::autoObjectPtr;
|
||||
using girmem::autoObject;
|
||||
#include "xmlrpc-c/base.h"
|
||||
#include "xmlrpc-c/client.h"
|
||||
#include "xmlrpc-c/transport.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
|
||||
|
||||
#include "xmlrpc-c/base.hpp"
|
||||
#include "xmlrpc-c/xml.hpp"
|
||||
#include "xmlrpc-c/client.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace xmlrpc_c;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class memblockStringWrapper {
|
||||
|
||||
public:
|
||||
memblockStringWrapper(string const value) {
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
this->memblockP = XMLRPC_MEMBLOCK_NEW(char, &env, 0);
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
|
||||
XMLRPC_MEMBLOCK_APPEND(char, &env, this->memblockP,
|
||||
value.c_str(), value.size());
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
|
||||
memblockStringWrapper(xmlrpc_mem_block * const memblockP) :
|
||||
memblockP(memblockP) {};
|
||||
|
||||
~memblockStringWrapper() {
|
||||
XMLRPC_MEMBLOCK_FREE(char, this->memblockP);
|
||||
}
|
||||
|
||||
xmlrpc_mem_block * memblockP;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace xmlrpc_c {
|
||||
|
||||
carriageParm::carriageParm() {}
|
||||
|
||||
|
||||
|
||||
carriageParm::~carriageParm() {}
|
||||
|
||||
|
||||
|
||||
carriageParm_http0::carriageParm_http0() :
|
||||
c_serverInfoP(NULL) {}
|
||||
|
||||
|
||||
|
||||
carriageParm_http0::carriageParm_http0(string const serverUrl) {
|
||||
this->c_serverInfoP = NULL;
|
||||
|
||||
this->instantiate(serverUrl);
|
||||
}
|
||||
|
||||
|
||||
carriageParm_http0::~carriageParm_http0() {
|
||||
|
||||
if (this->c_serverInfoP)
|
||||
xmlrpc_server_info_free(this->c_serverInfoP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
carriageParm_http0::instantiate(string const serverUrl) {
|
||||
|
||||
if (c_serverInfoP)
|
||||
throw(error("object already instantiated"));
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
this->c_serverInfoP = xmlrpc_server_info_new(&env, serverUrl.c_str());
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
carriageParm_http0::setBasicAuth(string const username,
|
||||
string const password) {
|
||||
|
||||
if (!c_serverInfoP)
|
||||
throw(error("object not instantiated"));
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
xmlrpc_server_info_set_basic_auth(
|
||||
&env, this->c_serverInfoP, username.c_str(), password.c_str());
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
|
||||
|
||||
|
||||
carriageParm_curl0::carriageParm_curl0(
|
||||
string const serverUrl
|
||||
) {
|
||||
|
||||
this->instantiate(serverUrl);
|
||||
}
|
||||
|
||||
|
||||
carriageParm_libwww0::carriageParm_libwww0(
|
||||
string const serverUrl
|
||||
) {
|
||||
|
||||
this->instantiate(serverUrl);
|
||||
}
|
||||
|
||||
|
||||
|
||||
carriageParm_wininet0::carriageParm_wininet0(
|
||||
string const serverUrl
|
||||
) {
|
||||
|
||||
this->instantiate(serverUrl);
|
||||
}
|
||||
|
||||
|
||||
|
||||
xmlTransaction::xmlTransaction() {}
|
||||
|
||||
|
||||
|
||||
void
|
||||
xmlTransaction::finish(string const& responseXml) const {
|
||||
|
||||
xml::trace("XML-RPC RESPONSE", responseXml);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
xmlTransaction::finishErr(error const&) const {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
xmlTransactionPtr::xmlTransactionPtr() {}
|
||||
|
||||
|
||||
|
||||
xmlTransaction *
|
||||
xmlTransactionPtr::operator->() const {
|
||||
autoObject * const p(this->objectP);
|
||||
return dynamic_cast<xmlTransaction *>(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
clientXmlTransport::~clientXmlTransport() {}
|
||||
|
||||
|
||||
|
||||
void
|
||||
clientXmlTransport::start(carriageParm * const carriageParmP,
|
||||
string const& callXml,
|
||||
xmlTransactionPtr const& xmlTranP) {
|
||||
|
||||
string responseXml;
|
||||
|
||||
this->call(carriageParmP, callXml, &responseXml);
|
||||
|
||||
xmlTranP->finish(responseXml);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
clientXmlTransport::finishAsync(xmlrpc_c::timeout const timeout) {
|
||||
if (timeout.finite == timeout.finite)
|
||||
throw(error("This class does not have finishAsync()"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
clientXmlTransport::asyncComplete(
|
||||
struct xmlrpc_call_info * const callInfoP,
|
||||
xmlrpc_mem_block * const responseXmlMP,
|
||||
xmlrpc_env const transportEnv) {
|
||||
|
||||
xmlTransactionPtr * const xmlTranPP =
|
||||
reinterpret_cast<xmlTransactionPtr *>(callInfoP);
|
||||
|
||||
try {
|
||||
if (transportEnv.fault_occurred) {
|
||||
(*xmlTranPP)->finishErr(error(transportEnv.fault_string));
|
||||
} else {
|
||||
string const responseXml(
|
||||
XMLRPC_MEMBLOCK_CONTENTS(char, responseXmlMP),
|
||||
XMLRPC_MEMBLOCK_SIZE(char, responseXmlMP));
|
||||
(*xmlTranPP)->finish(responseXml);
|
||||
}
|
||||
} catch(error) {
|
||||
/* We can't throw an error back to C code, and the async_complete
|
||||
interface does not provide for failure, so we define ->finish()
|
||||
as not being capable of throwing an error.
|
||||
*/
|
||||
assert(false);
|
||||
}
|
||||
delete(xmlTranPP);
|
||||
|
||||
/* Ordinarily, *xmlTranPP is the last reference to **xmlTranPP
|
||||
(The xmlTransaction), so it will get destroyed too. But
|
||||
->finish() could conceivably create a new reference to
|
||||
**xmlTranPP, and then it would keep living.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
clientXmlTransport_http::~clientXmlTransport_http() {}
|
||||
|
||||
|
||||
|
||||
void
|
||||
clientXmlTransport_http::call(
|
||||
carriageParm * const carriageParmP,
|
||||
string const& callXml,
|
||||
string * const responseXmlP) {
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
carriageParm_http0 * const carriageParmHttpP =
|
||||
dynamic_cast<carriageParm_http0 *>(carriageParmP);
|
||||
|
||||
if (carriageParmHttpP == NULL)
|
||||
throw(error("HTTP client XML transport called with carriage "
|
||||
"parameter object not of class carriageParm_http"));
|
||||
|
||||
memblockStringWrapper callXmlM(callXml);
|
||||
|
||||
xmlrpc_mem_block * responseXmlMP;
|
||||
|
||||
this->c_transportOpsP->call(&env,
|
||||
this->c_transportP,
|
||||
carriageParmHttpP->c_serverInfoP,
|
||||
callXmlM.memblockP,
|
||||
&responseXmlMP);
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
|
||||
memblockStringWrapper responseHolder(responseXmlMP);
|
||||
// Makes responseXmlMP get freed at end of scope
|
||||
|
||||
*responseXmlP = string(XMLRPC_MEMBLOCK_CONTENTS(char, responseXmlMP),
|
||||
XMLRPC_MEMBLOCK_SIZE(char, responseXmlMP));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
clientXmlTransport_http::start(
|
||||
carriageParm * const carriageParmP,
|
||||
string const& callXml,
|
||||
xmlTransactionPtr const& xmlTranP) {
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
carriageParm_http0 * const carriageParmHttpP =
|
||||
dynamic_cast<carriageParm_http0 *>(carriageParmP);
|
||||
|
||||
if (carriageParmHttpP == NULL)
|
||||
throw(error("HTTP client XML transport called with carriage "
|
||||
"parameter object not of type carriageParm_http"));
|
||||
|
||||
memblockStringWrapper callXmlM(callXml);
|
||||
|
||||
/* xmlTranP2 is the reference to the XML transaction that is held by
|
||||
the running transaction, in C code. It lives in dynamically allocated
|
||||
storage and xmlTranP2P points to it.
|
||||
*/
|
||||
xmlTransactionPtr * const xmlTranP2P(new xmlTransactionPtr(xmlTranP));
|
||||
|
||||
try {
|
||||
this->c_transportOpsP->send_request(
|
||||
&env,
|
||||
this->c_transportP,
|
||||
carriageParmHttpP->c_serverInfoP,
|
||||
callXmlM.memblockP,
|
||||
&this->asyncComplete,
|
||||
reinterpret_cast<xmlrpc_call_info *>(xmlTranP2P));
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
} catch (...) {
|
||||
delete xmlTranP2P;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
clientXmlTransport_http::finishAsync(xmlrpc_c::timeout const timeout) {
|
||||
|
||||
xmlrpc_timeoutType const c_timeoutType(
|
||||
timeout.finite ? timeout_yes : timeout_no);
|
||||
xmlrpc_timeout const c_timeout(timeout.duration);
|
||||
|
||||
this->c_transportOpsP->finish_asynch(
|
||||
this->c_transportP, c_timeoutType, c_timeout);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if MUST_BUILD_CURL_CLIENT
|
||||
|
||||
clientXmlTransport_curl::clientXmlTransport_curl(
|
||||
string const networkInterface,
|
||||
bool const noSslVerifyPeer,
|
||||
bool const noSslVerifyHost,
|
||||
string const userAgent) {
|
||||
|
||||
struct xmlrpc_curl_xportparms transportParms;
|
||||
|
||||
transportParms.network_interface =
|
||||
networkInterface.size() > 0 ? networkInterface.c_str() : NULL;
|
||||
transportParms.no_ssl_verifypeer = noSslVerifyPeer;
|
||||
transportParms.no_ssl_verifyhost = noSslVerifyHost;
|
||||
transportParms.user_agent =
|
||||
userAgent.size() > 0 ? userAgent.c_str() : NULL;
|
||||
|
||||
this->c_transportOpsP = &xmlrpc_curl_transport_ops;
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
xmlrpc_curl_transport_ops.create(
|
||||
&env, 0, "", "", (xmlrpc_xportparms *)&transportParms,
|
||||
XMLRPC_CXPSIZE(user_agent),
|
||||
&this->c_transportP);
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
#else // MUST_BUILD_CURL_CLIENT
|
||||
|
||||
clientXmlTransport_curl::clientXmlTransport_curl(string, bool, bool, string) {
|
||||
|
||||
throw("There is no Curl client XML transport in this XML-RPC client "
|
||||
"library");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
clientXmlTransport_curl::~clientXmlTransport_curl() {
|
||||
|
||||
this->c_transportOpsP->destroy(this->c_transportP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if MUST_BUILD_LIBWWW_CLIENT
|
||||
|
||||
clientXmlTransport_libwww::clientXmlTransport_libwww(
|
||||
string const appname,
|
||||
string const appversion) {
|
||||
|
||||
this->c_transportOpsP = &xmlrpc_libwww_transport_ops;
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
xmlrpc_libwww_transport_ops.create(
|
||||
&env, 0, appname.c_str(), appversion.c_str(), NULL, 0,
|
||||
&this->c_transportP);
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
|
||||
#else // MUST_BUILD_LIBWWW_CLIENT
|
||||
clientXmlTransport_libwww::clientXmlTransport_libwww(string, string) {
|
||||
|
||||
throw(error("There is no Libwww client XML transport "
|
||||
"in this XML-RPC client library"));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
clientXmlTransport_libwww::~clientXmlTransport_libwww() {
|
||||
|
||||
this->c_transportOpsP->destroy(this->c_transportP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if MUST_BUILD_WININET_CLIENT
|
||||
|
||||
clientXmlTransport_wininet::clientXmlTransport_wininet(
|
||||
bool const allowInvalidSslCerts
|
||||
) {
|
||||
|
||||
struct xmlrpc_wininet_xportparms transportParms;
|
||||
|
||||
transportParms.allowInvalidSSLCerts = allowInvalidSslCerts;
|
||||
|
||||
this->c_transportOpsP = &xmlrpc_wininet_transport_ops;
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
xmlrpc_wininet_transport_ops.create(
|
||||
&env, 0, "", "", &transportParms, XMLRPC_WXPSIZE(allowInvalidSSLCerts),
|
||||
&this->c_transportP);
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
|
||||
#else // MUST_BUILD_WININET_CLIENT
|
||||
|
||||
clientXmlTransport_wininet::clientXmlTransport_wininet(bool const) {
|
||||
|
||||
throw(error("There is no Wininet client XML transport "
|
||||
"in this XML-RPC client library"));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
clientXmlTransport_wininet::~clientXmlTransport_wininet() {
|
||||
|
||||
this->c_transportOpsP->destroy(this->c_transportP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
clientTransaction::clientTransaction() {}
|
||||
|
||||
|
||||
|
||||
clientTransactionPtr::clientTransactionPtr() {}
|
||||
|
||||
|
||||
|
||||
clientTransactionPtr::~clientTransactionPtr() {}
|
||||
|
||||
|
||||
|
||||
clientTransaction *
|
||||
clientTransactionPtr::operator->() const {
|
||||
autoObject * const p(this->objectP);
|
||||
return dynamic_cast<clientTransaction *>(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
client::~client() {}
|
||||
|
||||
|
||||
void
|
||||
client::start(carriageParm * const carriageParmP,
|
||||
string const methodName,
|
||||
paramList const& paramList,
|
||||
clientTransactionPtr const& tranP) {
|
||||
/*----------------------------------------------------------------------------
|
||||
Start an RPC, wait for it to complete, and finish it.
|
||||
|
||||
Usually, a derived class overrides this with something that does
|
||||
not wait for the RPC to complete, but rather arranges for something
|
||||
to finish the RPC later when the RPC does complete.
|
||||
-----------------------------------------------------------------------------*/
|
||||
rpcOutcome outcome;
|
||||
|
||||
this->call(carriageParmP, methodName, paramList, &outcome);
|
||||
|
||||
tranP->finish(outcome);
|
||||
}
|
||||
|
||||
|
||||
|
||||
client_xml::client_xml(clientXmlTransport * const transportP) :
|
||||
transportP(transportP) {}
|
||||
|
||||
|
||||
|
||||
void
|
||||
client_xml::call(carriageParm * const carriageParmP,
|
||||
string const methodName,
|
||||
paramList const& paramList,
|
||||
rpcOutcome * const outcomeP) {
|
||||
|
||||
string callXml;
|
||||
string responseXml;
|
||||
|
||||
xml::generateCall(methodName, paramList, &callXml);
|
||||
|
||||
xml::trace("XML-RPC CALL", callXml);
|
||||
|
||||
this->transportP->call(carriageParmP, callXml, &responseXml);
|
||||
|
||||
xml::trace("XML-RPC RESPONSE", responseXml);
|
||||
|
||||
xml::parseResponse(responseXml, outcomeP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
client_xml::start(carriageParm * const carriageParmP,
|
||||
string const methodName,
|
||||
paramList const& paramList,
|
||||
clientTransactionPtr const& tranP) {
|
||||
|
||||
string callXml;
|
||||
|
||||
xml::generateCall(methodName, paramList, &callXml);
|
||||
|
||||
xml::trace("XML-RPC CALL", callXml);
|
||||
|
||||
xmlTransaction_clientPtr const xmlTranP(tranP);
|
||||
|
||||
this->transportP->start(carriageParmP, callXml, xmlTranP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
client_xml::finishAsync(xmlrpc_c::timeout const timeout) {
|
||||
|
||||
transportP->finishAsync(timeout);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
connection::connection(client * const clientP,
|
||||
carriageParm * const carriageParmP) :
|
||||
clientP(clientP), carriageParmP(carriageParmP) {}
|
||||
|
||||
|
||||
|
||||
connection::~connection() {}
|
||||
|
||||
|
||||
|
||||
rpc::rpc(string const methodName,
|
||||
xmlrpc_c::paramList const& paramList) {
|
||||
|
||||
this->state = STATE_UNFINISHED;
|
||||
this->methodName = methodName;
|
||||
this->paramList = paramList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
rpc::~rpc() {
|
||||
|
||||
if (this->state == STATE_ERROR)
|
||||
delete(this->errorP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
rpc::call(client * const clientP,
|
||||
carriageParm * const carriageParmP) {
|
||||
|
||||
if (this->state != STATE_UNFINISHED)
|
||||
throw(error("Attempt to execute an RPC that has already been "
|
||||
"executed"));
|
||||
|
||||
clientP->call(carriageParmP,
|
||||
this->methodName,
|
||||
this->paramList,
|
||||
&this->outcome);
|
||||
|
||||
this->state = outcome.succeeded() ? STATE_SUCCEEDED : STATE_FAILED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
rpc::call(connection const& connection) {
|
||||
|
||||
this->call(connection.clientP, connection.carriageParmP);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
rpc::start(client * const clientP,
|
||||
carriageParm * const carriageParmP) {
|
||||
|
||||
if (this->state != STATE_UNFINISHED)
|
||||
throw(error("Attempt to execute an RPC that has already been "
|
||||
"executed"));
|
||||
|
||||
clientP->start(carriageParmP,
|
||||
this->methodName,
|
||||
this->paramList,
|
||||
rpcPtr(this));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
rpc::start(xmlrpc_c::connection const& connection) {
|
||||
|
||||
this->start(connection.clientP, connection.carriageParmP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
rpc::finish(rpcOutcome const& outcome) {
|
||||
|
||||
this->state = outcome.succeeded() ? STATE_SUCCEEDED : STATE_FAILED;
|
||||
|
||||
this->outcome = outcome;
|
||||
|
||||
this->notifyComplete();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
rpc::finishErr(error const& error) {
|
||||
|
||||
this->state = STATE_ERROR;
|
||||
this->errorP = new girerr::error(error);
|
||||
this->notifyComplete();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
rpc::notifyComplete() {
|
||||
/*----------------------------------------------------------------------------
|
||||
Anyone who does RPCs asynchronously and doesn't use polling will
|
||||
want to make his own class derived from 'rpc' and override this
|
||||
with a notifyFinish() that does something.
|
||||
|
||||
Typically, notifyFinish() will queue the RPC so some other thread
|
||||
will deal with the fact that the RPC is finished.
|
||||
|
||||
|
||||
In the absence of the aforementioned queueing, the RPC becomes
|
||||
unreferenced as soon as our Caller releases his reference, so the
|
||||
RPC gets destroyed when we return.
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
value
|
||||
rpc::getResult() const {
|
||||
|
||||
switch (this->state) {
|
||||
case STATE_UNFINISHED:
|
||||
throw(error("Attempt to get result of RPC that is not finished."));
|
||||
break;
|
||||
case STATE_ERROR:
|
||||
throw(*this->errorP);
|
||||
break;
|
||||
case STATE_FAILED:
|
||||
throw(error("RPC failed. " +
|
||||
this->outcome.getFault().getDescription()));
|
||||
break;
|
||||
case STATE_SUCCEEDED: {
|
||||
// All normal
|
||||
}
|
||||
}
|
||||
|
||||
return this->outcome.getResult();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
fault
|
||||
rpc::getFault() const {
|
||||
|
||||
switch (this->state) {
|
||||
case STATE_UNFINISHED:
|
||||
throw(error("Attempt to get fault from RPC that is not finished"));
|
||||
break;
|
||||
case STATE_ERROR:
|
||||
throw(*this->errorP);
|
||||
break;
|
||||
case STATE_SUCCEEDED:
|
||||
throw(error("Attempt to get fault from an RPC that succeeded"));
|
||||
break;
|
||||
case STATE_FAILED: {
|
||||
// All normal
|
||||
}
|
||||
}
|
||||
|
||||
return this->outcome.getFault();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
rpc::isFinished() const {
|
||||
return (this->state != STATE_UNFINISHED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
rpc::isSuccessful() const {
|
||||
return (this->state == STATE_SUCCEEDED);
|
||||
}
|
||||
|
||||
|
||||
|
||||
rpcPtr::rpcPtr() {}
|
||||
|
||||
|
||||
|
||||
rpcPtr::rpcPtr(rpc * const rpcP) {
|
||||
this->instantiate(rpcP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
rpcPtr::rpcPtr(string const methodName,
|
||||
xmlrpc_c::paramList const& paramList) {
|
||||
|
||||
this->instantiate(new rpc(methodName, paramList));
|
||||
}
|
||||
|
||||
|
||||
|
||||
rpc *
|
||||
rpcPtr::operator->() const {
|
||||
|
||||
autoObject * const p(this->objectP);
|
||||
return dynamic_cast<rpc *>(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
xmlTransaction_client::xmlTransaction_client(
|
||||
clientTransactionPtr const& tranP) :
|
||||
tranP(tranP) {}
|
||||
|
||||
|
||||
|
||||
void
|
||||
xmlTransaction_client::finish(string const& responseXml) const {
|
||||
|
||||
xml::trace("XML-RPC RESPONSE", responseXml);
|
||||
|
||||
try {
|
||||
rpcOutcome outcome;
|
||||
|
||||
xml::parseResponse(responseXml, &outcome);
|
||||
|
||||
this->tranP->finish(outcome);
|
||||
} catch (error const caughtError) {
|
||||
this->tranP->finishErr(caughtError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
xmlTransaction_client::finishErr(error const& error) const {
|
||||
|
||||
this->tranP->finishErr(error);
|
||||
}
|
||||
|
||||
|
||||
|
||||
xmlTransaction_clientPtr::xmlTransaction_clientPtr() {}
|
||||
|
||||
|
||||
|
||||
xmlTransaction_clientPtr::xmlTransaction_clientPtr(
|
||||
clientTransactionPtr const& tranP) {
|
||||
|
||||
this->instantiate(new xmlTransaction_client(tranP));
|
||||
}
|
||||
|
||||
|
||||
|
||||
xmlTransaction_client *
|
||||
xmlTransaction_clientPtr::operator->() const {
|
||||
autoObject * const p(this->objectP);
|
||||
return dynamic_cast<xmlTransaction_client *>(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace
|
180
libs/xmlrpc-c/src/cpp/client_simple.cpp
Normal file
180
libs/xmlrpc-c/src/cpp/client_simple.cpp
Normal file
@@ -0,0 +1,180 @@
|
||||
#include <string>
|
||||
|
||||
#include "xmlrpc-c/girerr.hpp"
|
||||
using girerr::error;
|
||||
#include "xmlrpc-c/base.h"
|
||||
#include "xmlrpc-c/base.hpp"
|
||||
#include "xmlrpc-c/client.hpp"
|
||||
#include <xmlrpc-c/client.hpp>
|
||||
/* transport_config.h defines XMLRPC_DEFAULT_TRANSPORT,
|
||||
MUST_BUILD_WININET_CLIENT, MUST_BUILD_CURL_CLIENT,
|
||||
MUST_BUILD_LIBWWW_CLIENT
|
||||
*/
|
||||
#include "transport_config.h"
|
||||
|
||||
#include "xmlrpc-c/client_simple.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace xmlrpc_c;
|
||||
|
||||
namespace xmlrpc_c {
|
||||
|
||||
|
||||
namespace {
|
||||
/*----------------------------------------------------------------------------
|
||||
Use an object of this class to set up to remove a reference to an
|
||||
xmlrpc_value object (a C object with manual reference management)
|
||||
at then end of a scope -- even if the scope ends with a throw.
|
||||
-----------------------------------------------------------------------------*/
|
||||
class cValueWrapper {
|
||||
xmlrpc_value * valueP;
|
||||
public:
|
||||
cValueWrapper(xmlrpc_value * valueP) : valueP(valueP) {}
|
||||
~cValueWrapper() { xmlrpc_DECREF(valueP); }
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
clientSimple::clientSimple() {
|
||||
|
||||
if (string(XMLRPC_DEFAULT_TRANSPORT) == string("curl"))
|
||||
this->transportP = new clientXmlTransport_curl;
|
||||
else if (string(XMLRPC_DEFAULT_TRANSPORT) == string("libwww"))
|
||||
this->transportP = new clientXmlTransport_libwww;
|
||||
else if (string(XMLRPC_DEFAULT_TRANSPORT) == string("wininet"))
|
||||
this->transportP = new clientXmlTransport_wininet;
|
||||
else
|
||||
throw(error("INTERNAL ERROR: "
|
||||
"Default client XML transport is not one we recognize"));
|
||||
|
||||
this->clientP = new client_xml(transportP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
clientSimple::~clientSimple() {
|
||||
|
||||
delete this->clientP;
|
||||
delete this->transportP;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
clientSimple::call(string const serverUrl,
|
||||
string const methodName,
|
||||
value * const resultP) {
|
||||
|
||||
carriageParm_http0 carriageParm(serverUrl);
|
||||
|
||||
rpcPtr rpcPtr(methodName, paramList());
|
||||
|
||||
rpcPtr->call(this->clientP, &carriageParm);
|
||||
|
||||
*resultP = rpcPtr->getResult();
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
makeParamArray(string const format,
|
||||
xmlrpc_value ** const paramArrayPP,
|
||||
va_list args) {
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
/* The format is a sequence of parameter specifications, such as
|
||||
"iiii" for 4 integer parameters. We add parentheses to make it
|
||||
an array of those parameters: "(iiii)".
|
||||
*/
|
||||
string const arrayFormat("(" + string(format) + ")");
|
||||
const char * tail;
|
||||
|
||||
xmlrpc_build_value_va(&env, arrayFormat.c_str(),
|
||||
args, paramArrayPP, &tail);
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
|
||||
if (strlen(tail) != 0) {
|
||||
/* xmlrpc_build_value_va() parses off a single value specification
|
||||
from its format string, and 'tail' points to whatever is after
|
||||
it. Our format string should have been a single array value,
|
||||
meaning tail is end-of-string. If it's not, that means
|
||||
something closed our array early.
|
||||
*/
|
||||
xmlrpc_DECREF(*paramArrayPP);
|
||||
throw(error("format string is invalid. It apparently has a "
|
||||
"stray right parenthesis"));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
void
|
||||
clientSimple::call(string const serverUrl,
|
||||
string const methodName,
|
||||
string const format,
|
||||
value * const resultP,
|
||||
...) {
|
||||
|
||||
carriageParm_http0 carriageParm(serverUrl);
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
xmlrpc_value * paramArrayP;
|
||||
|
||||
va_list args;
|
||||
va_start(args, resultP);
|
||||
makeParamArray(format, ¶mArrayP, args);
|
||||
va_end(args);
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
else {
|
||||
cValueWrapper paramArrayWrapper(paramArrayP); // ensure destruction
|
||||
unsigned int const paramCount = xmlrpc_array_size(&env, paramArrayP);
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
|
||||
paramList paramList;
|
||||
for (unsigned int i = 0; i < paramCount; ++i) {
|
||||
xmlrpc_value * paramP;
|
||||
xmlrpc_array_read_item(&env, paramArrayP, i, ¶mP);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
else {
|
||||
cValueWrapper paramWrapper(paramP); // ensure destruction
|
||||
paramList.add(value(paramP));
|
||||
}
|
||||
}
|
||||
rpcPtr rpcPtr(methodName, paramList);
|
||||
rpcPtr->call(this->clientP, &carriageParm);
|
||||
*resultP = rpcPtr->getResult();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
clientSimple::call(string const serverUrl,
|
||||
string const methodName,
|
||||
paramList const& paramList,
|
||||
value * const resultP) {
|
||||
|
||||
carriageParm_http0 carriageParm(serverUrl);
|
||||
|
||||
rpcPtr rpcPtr(methodName, paramList);
|
||||
|
||||
rpcPtr->call(this->clientP, &carriageParm);
|
||||
|
||||
*resultP = rpcPtr->getResult();
|
||||
}
|
||||
|
||||
} // namespace
|
1187
libs/xmlrpc-c/src/cpp/cpptest.cpp
Normal file
1187
libs/xmlrpc-c/src/cpp/cpptest.cpp
Normal file
File diff suppressed because it is too large
Load Diff
35
libs/xmlrpc-c/src/cpp/fault.cpp
Normal file
35
libs/xmlrpc-c/src/cpp/fault.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include <string>
|
||||
|
||||
#include "xmlrpc-c/girerr.hpp"
|
||||
using girerr::error;
|
||||
#include "xmlrpc-c/base.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace xmlrpc_c {
|
||||
|
||||
fault::fault() : valid(false) {};
|
||||
|
||||
fault::fault(string const _description,
|
||||
xmlrpc_c::fault::code_t const _code
|
||||
) :
|
||||
valid(true),
|
||||
code(_code),
|
||||
description(_description)
|
||||
{}
|
||||
|
||||
xmlrpc_c::fault::code_t
|
||||
fault::getCode() const {
|
||||
if (!valid)
|
||||
throw(error("Attempt to access placeholder xmlrpc_c::fault object"));
|
||||
return this->code;
|
||||
}
|
||||
|
||||
string
|
||||
fault::getDescription() const {
|
||||
if (!valid)
|
||||
throw(error("Attempt to access placeholder xmlrpc_c::fault object"));
|
||||
return this->description;
|
||||
}
|
||||
|
||||
} // namespace
|
123
libs/xmlrpc-c/src/cpp/girmem.cpp
Normal file
123
libs/xmlrpc-c/src/cpp/girmem.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
#include "pthreadx.h"
|
||||
#include "xmlrpc-c/girerr.hpp"
|
||||
using girerr::error;
|
||||
#include "xmlrpc-c/girmem.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace girmem;
|
||||
|
||||
|
||||
namespace girmem {
|
||||
|
||||
|
||||
void
|
||||
autoObject::incref() {
|
||||
pthread_mutex_lock(&this->refcountLock);
|
||||
++this->refcount;
|
||||
pthread_mutex_unlock(&this->refcountLock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
autoObject::decref(bool * const unreferencedP) {
|
||||
|
||||
if (this->refcount == 0)
|
||||
throw(error("Decrementing ref count of unreferenced object"));
|
||||
pthread_mutex_lock(&this->refcountLock);
|
||||
--this->refcount;
|
||||
*unreferencedP = (this->refcount == 0);
|
||||
pthread_mutex_unlock(&this->refcountLock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
autoObject::autoObject() {
|
||||
int rc;
|
||||
|
||||
rc = pthread_mutex_init(&this->refcountLock, NULL);
|
||||
|
||||
if (rc != 0)
|
||||
throw(error("Unable to initialize pthread mutex"));
|
||||
|
||||
this->refcount = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
autoObject::~autoObject() {
|
||||
if (this->refcount > 0)
|
||||
throw(error("Destroying referenced object"));
|
||||
|
||||
int rc;
|
||||
|
||||
rc = pthread_mutex_destroy(&this->refcountLock);
|
||||
|
||||
if (rc != 0)
|
||||
throw(error("Unable to destroy pthread mutex"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
autoObjectPtr::autoObjectPtr() : objectP(NULL) {}
|
||||
|
||||
|
||||
|
||||
autoObjectPtr::autoObjectPtr(autoObject * const objectP) {
|
||||
this->objectP = objectP;
|
||||
objectP->incref();
|
||||
}
|
||||
|
||||
|
||||
|
||||
autoObjectPtr::autoObjectPtr(autoObjectPtr const& autoObjectPtr) {
|
||||
// copy constructor
|
||||
|
||||
this->objectP = autoObjectPtr.objectP;
|
||||
if (this->objectP)
|
||||
this->objectP->incref();
|
||||
}
|
||||
|
||||
|
||||
|
||||
autoObjectPtr::~autoObjectPtr() {
|
||||
if (this->objectP) {
|
||||
bool dead;
|
||||
this->objectP->decref(&dead);
|
||||
if (dead)
|
||||
delete(this->objectP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
autoObjectPtr::instantiate(autoObject * const objectP) {
|
||||
|
||||
this->objectP = objectP;
|
||||
objectP->incref();
|
||||
}
|
||||
|
||||
|
||||
|
||||
autoObjectPtr
|
||||
autoObjectPtr::operator=(autoObjectPtr const& autoObjectPtr) {
|
||||
|
||||
if (this->objectP != NULL)
|
||||
throw(error("Already instantiated"));
|
||||
this->objectP = autoObjectPtr.objectP;
|
||||
this->objectP->incref();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
autoObject *
|
||||
autoObjectPtr::operator->() const {
|
||||
return this->objectP;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace
|
57
libs/xmlrpc-c/src/cpp/outcome.cpp
Normal file
57
libs/xmlrpc-c/src/cpp/outcome.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#include "xmlrpc-c/girerr.hpp"
|
||||
using girerr::error;
|
||||
#include "xmlrpc-c/base.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace xmlrpc_c {
|
||||
|
||||
rpcOutcome::rpcOutcome() : valid(false) {}
|
||||
|
||||
rpcOutcome::rpcOutcome(xmlrpc_c::value const result) :
|
||||
valid(true), _succeeded(true), result(result)
|
||||
{}
|
||||
|
||||
|
||||
|
||||
rpcOutcome::rpcOutcome(xmlrpc_c::fault const fault) :
|
||||
valid(true), _succeeded(false), fault(fault)
|
||||
{}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
rpcOutcome::succeeded() const {
|
||||
if (!valid)
|
||||
throw(error("Attempt to access rpcOutcome object before setting it"));
|
||||
return _succeeded;
|
||||
}
|
||||
|
||||
|
||||
|
||||
fault
|
||||
rpcOutcome::getFault() const {
|
||||
|
||||
if (!valid)
|
||||
throw(error("Attempt to access rpcOutcome object before setting it"));
|
||||
if (_succeeded)
|
||||
throw(error("Attempt to get fault description from a non-failure "
|
||||
"RPC outcome"));
|
||||
return fault;
|
||||
}
|
||||
|
||||
|
||||
|
||||
value
|
||||
rpcOutcome::getResult() const {
|
||||
|
||||
if (!valid)
|
||||
throw(error("Attempt to access rpcOutcome object before setting it"));
|
||||
if (!_succeeded)
|
||||
throw(error("Attempt to get result from an unsuccessful RPC outcome"));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
259
libs/xmlrpc-c/src/cpp/param_list.cpp
Normal file
259
libs/xmlrpc-c/src/cpp/param_list.cpp
Normal file
@@ -0,0 +1,259 @@
|
||||
#include <climits>
|
||||
#include <cfloat>
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
|
||||
#include "xmlrpc-c/girerr.hpp"
|
||||
using girerr::error;
|
||||
#include "xmlrpc-c/base.h"
|
||||
#include "xmlrpc-c/base.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace xmlrpc_c;
|
||||
|
||||
namespace xmlrpc_c {
|
||||
|
||||
|
||||
paramList::paramList(unsigned int const paramCount) {
|
||||
|
||||
this->paramVector.reserve(paramCount);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
paramList::add(xmlrpc_c::value const param) {
|
||||
|
||||
this->paramVector.push_back(param);
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned int
|
||||
paramList::size() const {
|
||||
return this->paramVector.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
xmlrpc_c::value
|
||||
paramList::operator[](unsigned int const subscript) const {
|
||||
|
||||
if (subscript >= this->paramVector.size())
|
||||
throw(girerr::error(
|
||||
"Subscript of xmlrpc_c::paramList out of bounds"));
|
||||
|
||||
return this->paramVector[subscript];
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
paramList::getInt(unsigned int const paramNumber,
|
||||
int const minimum,
|
||||
int const maximum) const {
|
||||
|
||||
if (paramNumber >= this->paramVector.size())
|
||||
throw(fault("Not enough parameters", fault::CODE_TYPE));
|
||||
|
||||
if (this->paramVector[paramNumber].type() != value::TYPE_INT)
|
||||
throw(fault("Parameter that is supposed to be integer is not",
|
||||
fault::CODE_TYPE));
|
||||
|
||||
int const intvalue(static_cast<int>(
|
||||
value_int(this->paramVector[paramNumber])));
|
||||
|
||||
if (intvalue < minimum)
|
||||
throw(fault("Integer parameter too low", fault::CODE_TYPE));
|
||||
|
||||
if (intvalue > maximum)
|
||||
throw(fault("Integer parameter too high", fault::CODE_TYPE));
|
||||
|
||||
return intvalue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
paramList::getBoolean(unsigned int const paramNumber) const {
|
||||
|
||||
if (paramNumber >= this->paramVector.size())
|
||||
throw(fault("Not enough parameters", fault::CODE_TYPE));
|
||||
|
||||
if (this->paramVector[paramNumber].type() != value::TYPE_BOOLEAN)
|
||||
throw(fault("Parameter that is supposed to be boolean is not",
|
||||
fault::CODE_TYPE));
|
||||
|
||||
return static_cast<bool>(value_boolean(this->paramVector[paramNumber]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
double
|
||||
paramList::getDouble(unsigned int const paramNumber,
|
||||
double const minimum,
|
||||
double const maximum) const {
|
||||
|
||||
if (paramNumber >= this->paramVector.size())
|
||||
throw(fault("Not enough parameters", fault::CODE_TYPE));
|
||||
|
||||
if (this->paramVector[paramNumber].type() != value::TYPE_DOUBLE)
|
||||
throw(fault("Parameter that is supposed to be floating point number "
|
||||
"is not",
|
||||
fault::CODE_TYPE));
|
||||
|
||||
double const doublevalue(static_cast<double>(
|
||||
value_double(this->paramVector[paramNumber])));
|
||||
|
||||
if (doublevalue < minimum)
|
||||
throw(fault("Floating point number parameter too low",
|
||||
fault::CODE_TYPE));
|
||||
|
||||
if (doublevalue > maximum)
|
||||
throw(fault("Floating point number parameter too high",
|
||||
fault::CODE_TYPE));
|
||||
|
||||
return doublevalue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
time_t
|
||||
paramList::getDatetime_sec(
|
||||
unsigned int const paramNumber,
|
||||
paramList::timeConstraint const constraint) const {
|
||||
|
||||
if (paramNumber >= this->paramVector.size())
|
||||
throw(fault("Not enough parameters", fault::CODE_TYPE));
|
||||
|
||||
const xmlrpc_c::value * const paramP(&this->paramVector[paramNumber]);
|
||||
|
||||
if (paramP->type() != value::TYPE_DATETIME)
|
||||
throw(fault("Parameter that is supposed to be a datetime is not",
|
||||
fault::CODE_TYPE));
|
||||
|
||||
time_t const timeValue(static_cast<time_t>(value_datetime(*paramP)));
|
||||
time_t const now(time(NULL));
|
||||
|
||||
switch (constraint) {
|
||||
case TC_ANY:
|
||||
/* He'll take anything; no problem */
|
||||
break;
|
||||
case TC_NO_FUTURE:
|
||||
if (timeValue > now)
|
||||
throw(fault("Datetime parameter that is not supposed to be in "
|
||||
"the future is.", fault::CODE_TYPE));
|
||||
break;
|
||||
case TC_NO_PAST:
|
||||
if (timeValue < now)
|
||||
throw(fault("Datetime parameter that is not supposed to be in "
|
||||
"the past is.", fault::CODE_TYPE));
|
||||
break;
|
||||
}
|
||||
|
||||
return timeValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
string
|
||||
paramList::getString(unsigned int const paramNumber) const {
|
||||
|
||||
if (paramNumber >= this->paramVector.size())
|
||||
throw(fault("Not enough parameters", fault::CODE_TYPE));
|
||||
|
||||
if (this->paramVector[paramNumber].type() != value::TYPE_STRING)
|
||||
throw(fault("Parameter that is supposed to be a string is not",
|
||||
fault::CODE_TYPE));
|
||||
|
||||
return static_cast<string>(value_string(this->paramVector[paramNumber]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<unsigned char>
|
||||
paramList::getBytestring(unsigned int const paramNumber) const {
|
||||
|
||||
if (paramNumber >= this->paramVector.size())
|
||||
throw(fault("Not enough parameters", fault::CODE_TYPE));
|
||||
|
||||
const xmlrpc_c::value * const paramP(&this->paramVector[paramNumber]);
|
||||
|
||||
if (paramP->type() != value::TYPE_BYTESTRING)
|
||||
throw(fault("Parameter that is supposed to be a byte string is not",
|
||||
fault::CODE_TYPE));
|
||||
|
||||
return value_bytestring(*paramP).vectorUcharValue();
|
||||
}
|
||||
|
||||
|
||||
std::vector<xmlrpc_c::value>
|
||||
paramList::getArray(unsigned int const paramNumber,
|
||||
unsigned int const minSize,
|
||||
unsigned int const maxSize) const {
|
||||
|
||||
if (paramNumber >= this->paramVector.size())
|
||||
throw(fault("Not enough parameters", fault::CODE_TYPE));
|
||||
|
||||
const xmlrpc_c::value * const paramP(&this->paramVector[paramNumber]);
|
||||
|
||||
if (paramP->type() != value::TYPE_ARRAY)
|
||||
throw(fault("Parameter that is supposed to be an array is not",
|
||||
fault::CODE_TYPE));
|
||||
|
||||
xmlrpc_c::value_array const arrayValue(*paramP);
|
||||
|
||||
if (arrayValue.size() < minSize)
|
||||
throw(fault("Array parameter has too few elements",
|
||||
fault::CODE_TYPE));
|
||||
|
||||
if (arrayValue.size() > maxSize)
|
||||
throw(fault("Array parameter has too many elements",
|
||||
fault::CODE_TYPE));
|
||||
|
||||
return value_array(*paramP).vectorValueValue();
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::map<string, xmlrpc_c::value>
|
||||
paramList::getStruct(unsigned int const paramNumber) const {
|
||||
|
||||
if (paramNumber >= this->paramVector.size())
|
||||
throw(fault("Not enough parameters", fault::CODE_TYPE));
|
||||
|
||||
const xmlrpc_c::value * const paramP(&this->paramVector[paramNumber]);
|
||||
|
||||
if (paramP->type() != value::TYPE_STRUCT)
|
||||
throw(fault("Parameter that is supposed to be a structure is not",
|
||||
fault::CODE_TYPE));
|
||||
|
||||
return static_cast<std::map<string, xmlrpc_c::value> >(
|
||||
value_struct(*paramP));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
paramList::getNil(unsigned int const paramNumber) const {
|
||||
|
||||
if (paramNumber >= this->paramVector.size())
|
||||
throw(fault("Not enough parameters", fault::CODE_TYPE));
|
||||
|
||||
if (this->paramVector[paramNumber].type() != value::TYPE_NIL)
|
||||
throw(fault("Parameter that is supposed to be nil is not",
|
||||
fault::CODE_TYPE));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
paramList::verifyEnd(unsigned int const paramNumber) const {
|
||||
|
||||
if (paramNumber < this->paramVector.size())
|
||||
throw(fault("Too many parameters", fault::CODE_TYPE));
|
||||
if (paramNumber > this->paramVector.size())
|
||||
throw(fault("Not enough parameters", fault::CODE_TYPE));
|
||||
}
|
||||
|
||||
} // namespace
|
341
libs/xmlrpc-c/src/cpp/registry.cpp
Normal file
341
libs/xmlrpc-c/src/cpp/registry.cpp
Normal file
@@ -0,0 +1,341 @@
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
|
||||
#include "xmlrpc-c/girerr.hpp"
|
||||
using girerr::error;
|
||||
#include "xmlrpc-c/girmem.hpp"
|
||||
using girmem::autoObject;
|
||||
using girmem::autoObjectPtr;
|
||||
#include "xmlrpc-c/base.h"
|
||||
#include "xmlrpc-c/base.hpp"
|
||||
#include "xmlrpc-c/registry.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace xmlrpc_c;
|
||||
|
||||
namespace xmlrpc_c {
|
||||
|
||||
|
||||
method::method() :
|
||||
_signature("?"),
|
||||
_help("No help is available for this method")
|
||||
{};
|
||||
|
||||
|
||||
|
||||
method *
|
||||
method::self() {
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
method::~method() {}
|
||||
|
||||
|
||||
|
||||
methodPtr::methodPtr(method * const methodP) {
|
||||
this->instantiate(methodP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
method *
|
||||
methodPtr::operator->() const {
|
||||
|
||||
autoObject * const p(this->objectP);
|
||||
return dynamic_cast<method *>(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
defaultMethod::~defaultMethod() {}
|
||||
|
||||
|
||||
|
||||
defaultMethodPtr::defaultMethodPtr() {}
|
||||
|
||||
|
||||
defaultMethodPtr::defaultMethodPtr(defaultMethod * const methodP) {
|
||||
this->instantiate(methodP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
defaultMethod *
|
||||
defaultMethodPtr::operator->() const {
|
||||
|
||||
autoObject * const p(this->objectP);
|
||||
return dynamic_cast<defaultMethod *>(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
defaultMethod *
|
||||
defaultMethod::self() {
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
registry::registry() {
|
||||
|
||||
xmlrpc_env env;
|
||||
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
this->c_registryP = xmlrpc_registry_new(&env);
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
|
||||
|
||||
|
||||
registry::~registry(void) {
|
||||
|
||||
xmlrpc_registry_free(this->c_registryP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static xmlrpc_c::paramList
|
||||
pListFromXmlrpcArray(xmlrpc_value * const arrayP) {
|
||||
/*----------------------------------------------------------------------------
|
||||
Convert an XML-RPC array in C (not C++) form to a parameter list object
|
||||
that can be passed to a method execute method.
|
||||
|
||||
This is glue code to allow us to hook up C++ Xmlrpc-c code to
|
||||
C Xmlrpc-c code.
|
||||
-----------------------------------------------------------------------------*/
|
||||
xmlrpc_env env;
|
||||
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
XMLRPC_ASSERT_ARRAY_OK(arrayP);
|
||||
|
||||
unsigned int const arraySize = xmlrpc_array_size(&env, arrayP);
|
||||
|
||||
xmlrpc_c::paramList paramList(arraySize);
|
||||
|
||||
for (unsigned int i = 0; i < arraySize; ++i) {
|
||||
xmlrpc_value * arrayItemP;
|
||||
xmlrpc_array_read_item(&env, arrayP, i, &arrayItemP);
|
||||
|
||||
paramList.add(xmlrpc_c::value(arrayItemP));
|
||||
|
||||
xmlrpc_DECREF(arrayItemP);
|
||||
}
|
||||
return paramList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static xmlrpc_value *
|
||||
c_executeMethod(xmlrpc_env * const envP,
|
||||
xmlrpc_value * const paramArrayP,
|
||||
void * const methodPtr) {
|
||||
/*----------------------------------------------------------------------------
|
||||
This is a function designed to be called via a C registry to
|
||||
execute an XML-RPC method, but use a C++ method object to do the
|
||||
work. You register this function as the method function and a
|
||||
pointer to the C++ method object as the method data in the C
|
||||
registry.
|
||||
|
||||
If we had a pure C++ registry, this would be unnecessary.
|
||||
|
||||
Since we can't throw an error back to the C code, we catch anything
|
||||
the XML-RPC method's execute() method throws, and any error we
|
||||
encounter in processing the result it returns, and turn it into an
|
||||
XML-RPC method failure. This will cause a leak if the execute()
|
||||
method actually created a result, since it will not get destroyed.
|
||||
-----------------------------------------------------------------------------*/
|
||||
xmlrpc_c::method * const methodP =
|
||||
static_cast<xmlrpc_c::method *>(methodPtr);
|
||||
xmlrpc_c::paramList const paramList(pListFromXmlrpcArray(paramArrayP));
|
||||
|
||||
xmlrpc_value * retval;
|
||||
|
||||
try {
|
||||
xmlrpc_c::value result;
|
||||
|
||||
try {
|
||||
methodP->execute(paramList, &result);
|
||||
} catch (xmlrpc_c::fault caughtFault) {
|
||||
xmlrpc_env_set_fault(envP, caughtFault.getCode(),
|
||||
caughtFault.getDescription().c_str());
|
||||
} catch (girerr::error caughtError) {
|
||||
xmlrpc_env_set_fault(envP, 0, caughtError.what());
|
||||
}
|
||||
if (envP->fault_occurred)
|
||||
retval = NULL;
|
||||
else
|
||||
retval = result.cValue();
|
||||
} catch (...) {
|
||||
xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
|
||||
"Unexpected error executing the code for this "
|
||||
"particular method, detected by the Xmlrpc-c "
|
||||
"method registry code. The method did not "
|
||||
"fail; rather, it did not complete at all.");
|
||||
retval = NULL;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static xmlrpc_value *
|
||||
c_executeDefaultMethod(xmlrpc_env * const envP,
|
||||
const char * const , // host
|
||||
const char * const methodName,
|
||||
xmlrpc_value * const paramArrayP,
|
||||
void * const methodPtr) {
|
||||
/*----------------------------------------------------------------------------
|
||||
This is a function designed to be called via a C registry to
|
||||
execute an XML-RPC method, but use a C++ method object to do the
|
||||
work. You register this function as the default method function and a
|
||||
pointer to the C++ default method object as the method data in the C
|
||||
registry.
|
||||
|
||||
If we had a pure C++ registry, this would be unnecessary.
|
||||
|
||||
Since we can't throw an error back to the C code, we catch anything
|
||||
the XML-RPC method's execute() method throws, and any error we
|
||||
encounter in processing the result it returns, and turn it into an
|
||||
XML-RPC method failure. This will cause a leak if the execute()
|
||||
method actually created a result, since it will not get destroyed.
|
||||
-----------------------------------------------------------------------------*/
|
||||
xmlrpc_c::defaultMethod * const methodP =
|
||||
static_cast<xmlrpc_c::defaultMethod *>(methodPtr);
|
||||
xmlrpc_c::paramList const paramList(pListFromXmlrpcArray(paramArrayP));
|
||||
|
||||
xmlrpc_value * retval;
|
||||
|
||||
try {
|
||||
xmlrpc_c::value result;
|
||||
|
||||
try {
|
||||
methodP->execute(methodName, paramList, &result);
|
||||
} catch (xmlrpc_c::fault caughtFault) {
|
||||
xmlrpc_env_set_fault(envP, caughtFault.getCode(),
|
||||
caughtFault.getDescription().c_str());
|
||||
} catch (girerr::error caughtError) {
|
||||
xmlrpc_env_set_fault(envP, 0, caughtError.what());
|
||||
}
|
||||
if (envP->fault_occurred)
|
||||
retval = NULL;
|
||||
else
|
||||
retval = result.cValue();
|
||||
} catch (...) {
|
||||
xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR,
|
||||
"Unexpected error executing the default "
|
||||
"method code, detected by the Xmlrpc-c "
|
||||
"method registry code. The method did not "
|
||||
"fail; rather, it did not complete at all.");
|
||||
retval = NULL;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
registry::addMethod(string const name,
|
||||
xmlrpc_c::methodPtr const methodPtr) {
|
||||
|
||||
|
||||
this->methodList.push_back(methodPtr);
|
||||
|
||||
xmlrpc_env env;
|
||||
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
xmlrpc_c::method * const methodP(methodPtr->self());
|
||||
|
||||
xmlrpc_registry_add_method_w_doc(
|
||||
&env, this->c_registryP, NULL,
|
||||
name.c_str(), &c_executeMethod,
|
||||
(void*) methodP,
|
||||
methodP->signature().c_str(), methodP->help().c_str());
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
registry::setDefaultMethod(defaultMethodPtr const methodPtr) {
|
||||
|
||||
xmlrpc_env env;
|
||||
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
this->defaultMethodP = methodPtr;
|
||||
|
||||
xmlrpc_c::defaultMethod * const methodP(methodPtr->self());
|
||||
|
||||
xmlrpc_registry_set_default_method(
|
||||
&env, this->c_registryP, &c_executeDefaultMethod, (void*) methodP);
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
registry::disableIntrospection() {
|
||||
|
||||
xmlrpc_registry_disable_introspection(this->c_registryP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
registry::processCall(string const& callXml,
|
||||
string * const responseXmlP) const {
|
||||
/*----------------------------------------------------------------------------
|
||||
Process an XML-RPC call whose XML is 'callXml'.
|
||||
|
||||
Return the response XML as *responseXmlP.
|
||||
|
||||
If we are unable to execute the call, we throw an error. But if
|
||||
the call executes and the method merely fails in an XML-RPC sense, we
|
||||
don't. In that case, *responseXmlP indicates the failure.
|
||||
-----------------------------------------------------------------------------*/
|
||||
xmlrpc_env env;
|
||||
xmlrpc_mem_block * output;
|
||||
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
// For the pure C++ version, this will have to parse 'callXml'
|
||||
// into a method name and parameters, look up the method name in
|
||||
// the registry, call the method's execute() method, then marshall
|
||||
// the result into XML and return it as *responseXmlP. It will
|
||||
// also have to execute system methods (e.g. introspection)
|
||||
// itself. This will be more or less like what
|
||||
// xmlrpc_registry_process_call() does.
|
||||
|
||||
output = xmlrpc_registry_process_call(
|
||||
&env, this->c_registryP, NULL, callXml.c_str(), callXml.length());
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
|
||||
*responseXmlP = string(XMLRPC_MEMBLOCK_CONTENTS(char, output),
|
||||
XMLRPC_MEMBLOCK_SIZE(char, output));
|
||||
|
||||
xmlrpc_mem_block_free(output);
|
||||
}
|
||||
|
||||
xmlrpc_registry *
|
||||
registry::c_registry() const {
|
||||
|
||||
return this->c_registryP;
|
||||
}
|
||||
|
||||
} // namespace
|
196
libs/xmlrpc-c/src/cpp/server_abyss.cpp
Normal file
196
libs/xmlrpc-c/src/cpp/server_abyss.cpp
Normal file
@@ -0,0 +1,196 @@
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "xmlrpc-c/girerr.hpp"
|
||||
using girerr::error;
|
||||
#include "xmlrpc-c/base.h"
|
||||
#include "xmlrpc-c/base.hpp"
|
||||
#include "xmlrpc-c/server_abyss.h"
|
||||
#include "xmlrpc-c/registry.hpp"
|
||||
#include "xmlrpc-c/server_abyss.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace xmlrpc_c;
|
||||
|
||||
namespace xmlrpc_c {
|
||||
|
||||
serverAbyss::serverAbyss(
|
||||
xmlrpc_c::registry const& registry,
|
||||
unsigned int const portNumber,
|
||||
string const& logFileName,
|
||||
unsigned int const keepaliveTimeout,
|
||||
unsigned int const keepaliveMaxConn,
|
||||
unsigned int const timeout,
|
||||
bool const dontAdvertise) {
|
||||
|
||||
this->registryP = ®istry;
|
||||
this->logFileName = logFileName;
|
||||
this->keepaliveTimeout = keepaliveTimeout;
|
||||
this->keepaliveMaxConn = keepaliveMaxConn;
|
||||
this->timeout = timeout;
|
||||
this->dontAdvertise = dontAdvertise;
|
||||
|
||||
if (portNumber > 0xffff)
|
||||
throw(error("Port number exceeds the maximum possible port number "
|
||||
"(65535)"));
|
||||
else {
|
||||
this->portNumber = portNumber;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
serverAbyss::~serverAbyss() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
static void
|
||||
sigterm(int const sig) {
|
||||
TraceExit("Signal %d received. Exiting...\n",sig);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sigchld(int const sig) {
|
||||
/*----------------------------------------------------------------------------
|
||||
This is a signal handler for a SIGCHLD signal (which informs us that
|
||||
one of our child processes has terminated).
|
||||
|
||||
We respond by reaping the zombie process.
|
||||
|
||||
Implementation note: In some systems, just setting the signal handler
|
||||
to SIG_IGN (ignore signal) does this. In others, it doesn't.
|
||||
-----------------------------------------------------------------------------*/
|
||||
#ifndef _WIN32
|
||||
/* Reap zombie children until there aren't any more. */
|
||||
|
||||
bool zombiesExist;
|
||||
bool error;
|
||||
|
||||
assert(sig == SIGCHLD);
|
||||
|
||||
zombiesExist = true; // initial assumption
|
||||
error = false; // no error yet
|
||||
while (zombiesExist && !error) {
|
||||
int status;
|
||||
pid_t const pid = waitpid((pid_t) -1, &status, WNOHANG);
|
||||
|
||||
if (pid == 0)
|
||||
zombiesExist = false;
|
||||
else if (pid < 0) {
|
||||
/* because of ptrace */
|
||||
if (errno == EINTR) {
|
||||
// This is OK - it's a ptrace notification
|
||||
} else
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
|
||||
void
|
||||
setupSignalHandlers(void) {
|
||||
#ifndef _WIN32
|
||||
struct sigaction mysigaction;
|
||||
|
||||
sigemptyset(&mysigaction.sa_mask);
|
||||
mysigaction.sa_flags = 0;
|
||||
|
||||
/* These signals abort the program, with tracing */
|
||||
mysigaction.sa_handler = sigterm;
|
||||
sigaction(SIGTERM, &mysigaction, NULL);
|
||||
sigaction(SIGINT, &mysigaction, NULL);
|
||||
sigaction(SIGHUP, &mysigaction, NULL);
|
||||
sigaction(SIGUSR1, &mysigaction, NULL);
|
||||
|
||||
/* This signal indicates connection closed in the middle */
|
||||
mysigaction.sa_handler = SIG_IGN;
|
||||
sigaction(SIGPIPE, &mysigaction, NULL);
|
||||
|
||||
/* This signal indicates a child process (request handler) has died */
|
||||
mysigaction.sa_handler = sigchld;
|
||||
sigaction(SIGCHLD, &mysigaction, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
setAdditionalServerParms(
|
||||
unsigned int const keepaliveTimeout,
|
||||
unsigned int const keepaliveMaxConn,
|
||||
unsigned int const timeout,
|
||||
bool const dontAdvertise,
|
||||
TServer * const srvP) {
|
||||
|
||||
/* The following ought to be parameters on ServerCreate(), but it
|
||||
looks like plugging them straight into the TServer structure is
|
||||
the only way to set them.
|
||||
*/
|
||||
|
||||
if (keepaliveTimeout > 0)
|
||||
srvP->keepalivetimeout = keepaliveTimeout;
|
||||
if (keepaliveMaxConn > 0)
|
||||
srvP->keepalivemaxconn = keepaliveMaxConn;
|
||||
if (timeout > 0)
|
||||
srvP->timeout = timeout;
|
||||
srvP->advertise = !dontAdvertise;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
void
|
||||
serverAbyss::run() {
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
DateInit();
|
||||
MIMETypeInit();
|
||||
|
||||
TServer srv;
|
||||
|
||||
const char * const logfileArg(this->logFileName.length() == 0 ?
|
||||
NULL : this->logFileName.c_str());
|
||||
|
||||
ServerCreate(&srv, "XmlRpcServer", this->portNumber,
|
||||
DEFAULT_DOCS, logfileArg);
|
||||
|
||||
setAdditionalServerParms(
|
||||
this->keepaliveTimeout, this->keepaliveMaxConn, this->timeout,
|
||||
this->dontAdvertise, &srv);
|
||||
|
||||
xmlrpc_c::server_abyss_set_handlers(&srv, *this->registryP);
|
||||
|
||||
ServerInit(&srv);
|
||||
|
||||
setupSignalHandlers();
|
||||
|
||||
ServerRun(&srv);
|
||||
|
||||
/* We can't exist here because ServerRun doesn't return */
|
||||
assert(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
server_abyss_set_handlers(TServer * const srvP,
|
||||
xmlrpc_c::registry const& registry) {
|
||||
|
||||
|
||||
xmlrpc_server_abyss_set_handlers(srvP, registry.c_registry());
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
807
libs/xmlrpc-c/src/cpp/value.cpp
Normal file
807
libs/xmlrpc-c/src/cpp/value.cpp
Normal file
@@ -0,0 +1,807 @@
|
||||
/*****************************************************************************
|
||||
xmlrpc_value.cpp
|
||||
******************************************************************************
|
||||
This module provides services for dealwith XML-RPC values. Each type
|
||||
of XML-RPC value is a C++ class. An object represents a particular
|
||||
XML-RPC value.
|
||||
|
||||
Everything is based on the C services in libxmlrpc.
|
||||
|
||||
We could make things more efficient by using the internal interfaces
|
||||
via xmlrpc_int.h. We could make them even more efficient by dumping
|
||||
libxmlrpc altogether for some or all of these services.
|
||||
|
||||
An xmlrpc_c::value object is really just a handle for a C xmlrpc_value
|
||||
object. You're not supposed to make a pointer to an xmlrpc_c::value
|
||||
object, but rather copy the object around.
|
||||
|
||||
Because the C xmlrpc_value object does reference counting, it
|
||||
disappears automatically when the last handle does. To go pure C++,
|
||||
we'd have to have a C++ object for the value itself and a separate
|
||||
handle object, like Boost's shared_ptr<>.
|
||||
|
||||
The C++ is designed so that the user never sees the C interface at
|
||||
all. Unfortunately, the user can see it if he wants because some
|
||||
class members had to be declared public so that other components of
|
||||
the library could see them, but the user is not supposed to access
|
||||
those members.
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <time.h>
|
||||
|
||||
#include "xmlrpc-c/girerr.hpp"
|
||||
using girerr::error;
|
||||
#include "xmlrpc-c/base.h"
|
||||
#include "xmlrpc-c/base_int.h"
|
||||
#include "xmlrpc-c/base.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace {
|
||||
|
||||
class cDatetimeValueWrapper {
|
||||
public:
|
||||
xmlrpc_value * valueP;
|
||||
|
||||
cDatetimeValueWrapper(time_t const cppvalue) {
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
this->valueP = xmlrpc_datetime_new_sec(&env, cppvalue);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
~cDatetimeValueWrapper() {
|
||||
xmlrpc_DECREF(this->valueP);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class cStringWrapper {
|
||||
public:
|
||||
const char * str;
|
||||
size_t length;
|
||||
cStringWrapper(xmlrpc_value * valueP) {
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
xmlrpc_read_string_lp(&env, valueP, &length, &str);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
~cStringWrapper() {
|
||||
free((char*)str);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
namespace xmlrpc_c {
|
||||
|
||||
value::value() {
|
||||
this->cValueP = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
value::value(xmlrpc_value * const valueP) { // default constructor
|
||||
|
||||
this->instantiate(valueP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
value::value(xmlrpc_c::value const& value) { // copy constructor
|
||||
this->cValueP = value.cValue();
|
||||
}
|
||||
|
||||
|
||||
|
||||
xmlrpc_c::value&
|
||||
value::operator=(xmlrpc_c::value const& value) {
|
||||
|
||||
if (this->cValueP != NULL)
|
||||
throw(error("Assigning to already instantiated xmlrpc_c::value"));
|
||||
|
||||
this->cValueP = value.cValue();
|
||||
return *this; // The result of the (a = b) expression
|
||||
}
|
||||
|
||||
|
||||
|
||||
value::~value() {
|
||||
if (this->cValueP) {
|
||||
xmlrpc_DECREF(this->cValueP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
value::instantiate(xmlrpc_value * const valueP) {
|
||||
|
||||
xmlrpc_INCREF(valueP);
|
||||
this->cValueP = valueP;
|
||||
}
|
||||
|
||||
|
||||
|
||||
xmlrpc_value *
|
||||
value::cValue() const {
|
||||
|
||||
if (this->cValueP) {
|
||||
xmlrpc_INCREF(this->cValueP); // For Caller
|
||||
}
|
||||
return this->cValueP;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
value::appendToCArray(xmlrpc_value * const arrayP) const {
|
||||
/*----------------------------------------------------------------------------
|
||||
Append this value to the C array 'arrayP'.
|
||||
----------------------------------------------------------------------------*/
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
xmlrpc_array_append_item(&env, arrayP, this->cValueP);
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
value::addToCStruct(xmlrpc_value * const structP,
|
||||
string const key) const {
|
||||
/*----------------------------------------------------------------------------
|
||||
Add this value to the C array 'arrayP' with key 'key'.
|
||||
----------------------------------------------------------------------------*/
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
xmlrpc_struct_set_value_n(&env, structP,
|
||||
key.c_str(), key.length(),
|
||||
this->cValueP);
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
|
||||
|
||||
|
||||
value::type_t
|
||||
value::type() const {
|
||||
/* You'd think we could just cast from xmlrpc_type to
|
||||
value:type_t, but Gcc warns if we do that. So we have to do this
|
||||
even messier union nonsense.
|
||||
*/
|
||||
union {
|
||||
xmlrpc_type x;
|
||||
value::type_t y;
|
||||
} u;
|
||||
|
||||
u.x = xmlrpc_value_type(this->cValueP);
|
||||
|
||||
return u.y;
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_int::value_int(int const cppvalue) {
|
||||
|
||||
class cWrapper {
|
||||
public:
|
||||
xmlrpc_value * valueP;
|
||||
|
||||
cWrapper(int const cppvalue) {
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
this->valueP = xmlrpc_int_new(&env, cppvalue);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
~cWrapper() {
|
||||
xmlrpc_DECREF(this->valueP);
|
||||
}
|
||||
};
|
||||
|
||||
cWrapper wrapper(cppvalue);
|
||||
|
||||
this->instantiate(wrapper.valueP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_int::value_int(xmlrpc_c::value const baseValue) {
|
||||
|
||||
if (baseValue.type() != xmlrpc_c::value::TYPE_INT)
|
||||
throw(error("Not integer type. See type() method"));
|
||||
else {
|
||||
this->instantiate(baseValue.cValueP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_int::operator int() const {
|
||||
|
||||
int retval;
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
xmlrpc_read_int(&env, this->cValueP, &retval);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_double::value_double(double const cppvalue) {
|
||||
|
||||
class cWrapper {
|
||||
public:
|
||||
xmlrpc_value * valueP;
|
||||
|
||||
cWrapper(double const cppvalue) {
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
this->valueP = xmlrpc_double_new(&env, cppvalue);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
~cWrapper() {
|
||||
xmlrpc_DECREF(this->valueP);
|
||||
}
|
||||
};
|
||||
|
||||
this->instantiate(cWrapper(cppvalue).valueP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_double::value_double(xmlrpc_c::value const baseValue) {
|
||||
|
||||
if (baseValue.type() != xmlrpc_c::value::TYPE_DOUBLE)
|
||||
throw(error("Not double type. See type() method"));
|
||||
else {
|
||||
this->instantiate(baseValue.cValueP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_double::operator double() const {
|
||||
|
||||
double retval;
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
xmlrpc_read_double(&env, this->cValueP, &retval);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_boolean::value_boolean(bool const cppvalue) {
|
||||
|
||||
class cWrapper {
|
||||
public:
|
||||
xmlrpc_value * valueP;
|
||||
|
||||
cWrapper(xmlrpc_bool const cppvalue) {
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
this->valueP = xmlrpc_bool_new(&env, cppvalue);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
~cWrapper() {
|
||||
xmlrpc_DECREF(this->valueP);
|
||||
}
|
||||
};
|
||||
|
||||
cWrapper wrapper(cppvalue);
|
||||
|
||||
this->instantiate(wrapper.valueP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_boolean::operator bool() const {
|
||||
|
||||
xmlrpc_bool retval;
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
xmlrpc_read_bool(&env, this->cValueP, &retval);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
|
||||
return (bool)retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_boolean::value_boolean(xmlrpc_c::value const baseValue) {
|
||||
|
||||
if (baseValue.type() != xmlrpc_c::value::TYPE_BOOLEAN)
|
||||
throw(error("Not boolean type. See type() method"));
|
||||
else {
|
||||
this->instantiate(baseValue.cValueP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_datetime::value_datetime(string const cppvalue) {
|
||||
|
||||
class cWrapper {
|
||||
public:
|
||||
xmlrpc_value * valueP;
|
||||
|
||||
cWrapper(string const cppvalue) {
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
this->valueP = xmlrpc_datetime_new_str(&env, cppvalue.c_str());
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
~cWrapper() {
|
||||
xmlrpc_DECREF(this->valueP);
|
||||
}
|
||||
};
|
||||
|
||||
cWrapper wrapper(cppvalue);
|
||||
|
||||
this->instantiate(wrapper.valueP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_datetime::value_datetime(time_t const cppvalue) {
|
||||
|
||||
cDatetimeValueWrapper wrapper(cppvalue);
|
||||
|
||||
this->instantiate(wrapper.valueP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_datetime::value_datetime(struct timeval const& cppvalue) {
|
||||
|
||||
cDatetimeValueWrapper wrapper(cppvalue.tv_sec);
|
||||
|
||||
this->instantiate(wrapper.valueP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_datetime::value_datetime(struct timespec const& cppvalue) {
|
||||
|
||||
cDatetimeValueWrapper wrapper(cppvalue.tv_sec);
|
||||
|
||||
this->instantiate(wrapper.valueP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_datetime::value_datetime(xmlrpc_c::value const baseValue) {
|
||||
|
||||
if (baseValue.type() != xmlrpc_c::value::TYPE_DATETIME)
|
||||
throw(error("Not datetime type. See type() method"));
|
||||
else {
|
||||
this->instantiate(baseValue.cValueP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_datetime::operator time_t() const {
|
||||
|
||||
time_t retval;
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
xmlrpc_read_datetime_sec(&env, this->cValueP, &retval);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_string::value_string(string const& cppvalue) {
|
||||
|
||||
class cWrapper {
|
||||
public:
|
||||
xmlrpc_value * valueP;
|
||||
|
||||
cWrapper(string const cppvalue) {
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
this->valueP = xmlrpc_string_new(&env, cppvalue.c_str());
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
~cWrapper() {
|
||||
xmlrpc_DECREF(this->valueP);
|
||||
}
|
||||
};
|
||||
|
||||
cWrapper wrapper(cppvalue);
|
||||
|
||||
this->instantiate(wrapper.valueP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_string::value_string(xmlrpc_c::value const baseValue) {
|
||||
|
||||
if (baseValue.type() != xmlrpc_c::value::TYPE_STRING)
|
||||
throw(error("Not string type. See type() method"));
|
||||
else {
|
||||
this->instantiate(baseValue.cValueP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_string::operator string() const {
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
cStringWrapper adapter(this->cValueP);
|
||||
|
||||
return string(adapter.str, adapter.length);
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_bytestring::value_bytestring(
|
||||
vector<unsigned char> const& cppvalue) {
|
||||
|
||||
class cWrapper {
|
||||
public:
|
||||
xmlrpc_value * valueP;
|
||||
|
||||
cWrapper(vector<unsigned char> const& cppvalue) {
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
this->valueP =
|
||||
xmlrpc_base64_new(&env, cppvalue.size(), &cppvalue[0]);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
~cWrapper() {
|
||||
xmlrpc_DECREF(this->valueP);
|
||||
}
|
||||
};
|
||||
|
||||
cWrapper wrapper(cppvalue);
|
||||
|
||||
this->instantiate(wrapper.valueP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
vector<unsigned char>
|
||||
value_bytestring::vectorUcharValue() const {
|
||||
|
||||
class cWrapper {
|
||||
public:
|
||||
const unsigned char * contents;
|
||||
size_t length;
|
||||
|
||||
cWrapper(xmlrpc_value * const valueP) {
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
xmlrpc_read_base64(&env, valueP, &length, &contents);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
~cWrapper() {
|
||||
free((void*)contents);
|
||||
}
|
||||
};
|
||||
|
||||
cWrapper wrapper(this->cValueP);
|
||||
|
||||
return vector<unsigned char>(&wrapper.contents[0],
|
||||
&wrapper.contents[wrapper.length]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t
|
||||
value_bytestring::length() const {
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
size_t length;
|
||||
xmlrpc_read_base64_size(&env, this->cValueP, &length);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_bytestring::value_bytestring(xmlrpc_c::value const baseValue) {
|
||||
|
||||
if (baseValue.type() != xmlrpc_c::value::TYPE_BYTESTRING)
|
||||
throw(error("Not byte string type. See type() method"));
|
||||
else {
|
||||
this->instantiate(baseValue.cValueP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_array::value_array(vector<xmlrpc_c::value> const& cppvalue) {
|
||||
|
||||
class cWrapper {
|
||||
public:
|
||||
xmlrpc_value * valueP;
|
||||
|
||||
cWrapper() {
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
this->valueP = xmlrpc_array_new(&env);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
~cWrapper() {
|
||||
xmlrpc_DECREF(this->valueP);
|
||||
}
|
||||
};
|
||||
|
||||
cWrapper wrapper;
|
||||
|
||||
vector<xmlrpc_c::value>::const_iterator i;
|
||||
for (i = cppvalue.begin(); i != cppvalue.end(); ++i)
|
||||
i->appendToCArray(wrapper.valueP);
|
||||
|
||||
this->instantiate(wrapper.valueP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_array::value_array(xmlrpc_c::value const baseValue) {
|
||||
|
||||
if (baseValue.type() != xmlrpc_c::value::TYPE_ARRAY)
|
||||
throw(error("Not array type. See type() method"));
|
||||
else {
|
||||
this->instantiate(baseValue.cValueP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
vector<xmlrpc_c::value>
|
||||
value_array::vectorValueValue() const {
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
unsigned int arraySize;
|
||||
|
||||
arraySize = xmlrpc_array_size(&env, this->cValueP);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
|
||||
vector<xmlrpc_c::value> retval(arraySize);
|
||||
|
||||
for (unsigned int i = 0; i < arraySize; ++i) {
|
||||
|
||||
class cWrapper {
|
||||
public:
|
||||
xmlrpc_value * valueP;
|
||||
|
||||
cWrapper(xmlrpc_value * const arrayP,
|
||||
unsigned int const index) {
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
xmlrpc_array_read_item(&env, arrayP, index, &valueP);
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
~cWrapper() {
|
||||
xmlrpc_DECREF(valueP);
|
||||
}
|
||||
};
|
||||
|
||||
cWrapper wrapper(this->cValueP, i);
|
||||
|
||||
retval[i].instantiate(wrapper.valueP);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
size_t
|
||||
value_array::size() const {
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
unsigned int arraySize;
|
||||
|
||||
arraySize = xmlrpc_array_size(&env, this->cValueP);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
|
||||
return arraySize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_struct::value_struct(
|
||||
map<string, xmlrpc_c::value> const &cppvalue) {
|
||||
|
||||
class cWrapper {
|
||||
public:
|
||||
xmlrpc_value * valueP;
|
||||
|
||||
cWrapper() {
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
this->valueP = xmlrpc_struct_new(&env);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
~cWrapper() {
|
||||
xmlrpc_DECREF(this->valueP);
|
||||
}
|
||||
};
|
||||
|
||||
cWrapper wrapper;
|
||||
|
||||
map<string, xmlrpc_c::value>::const_iterator i;
|
||||
for (i = cppvalue.begin(); i != cppvalue.end(); ++i) {
|
||||
xmlrpc_c::value mapvalue(i->second);
|
||||
string mapkey(i->first);
|
||||
mapvalue.addToCStruct(wrapper.valueP, mapkey);
|
||||
}
|
||||
|
||||
this->instantiate(wrapper.valueP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_struct::value_struct(xmlrpc_c::value const baseValue) {
|
||||
|
||||
if (baseValue.type() != xmlrpc_c::value::TYPE_STRUCT)
|
||||
throw(error("Not struct type. See type() method"));
|
||||
else {
|
||||
this->instantiate(baseValue.cValueP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_struct::operator map<string, xmlrpc_c::value>() const {
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
unsigned int structSize;
|
||||
|
||||
structSize = xmlrpc_struct_size(&env, this->cValueP);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
|
||||
map<string, xmlrpc_c::value> retval;
|
||||
|
||||
for (unsigned int i = 0; i < structSize; ++i) {
|
||||
class cMemberWrapper {
|
||||
public:
|
||||
xmlrpc_value * keyP;
|
||||
xmlrpc_value * valueP;
|
||||
|
||||
cMemberWrapper(xmlrpc_value * const structP,
|
||||
unsigned int const index) {
|
||||
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
xmlrpc_struct_read_member(&env, structP, index,
|
||||
&keyP, &valueP);
|
||||
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
~cMemberWrapper() {
|
||||
xmlrpc_DECREF(keyP);
|
||||
xmlrpc_DECREF(valueP);
|
||||
}
|
||||
};
|
||||
|
||||
cMemberWrapper memberWrapper(this->cValueP, i);
|
||||
|
||||
cStringWrapper keyWrapper(memberWrapper.keyP);
|
||||
|
||||
string const key(keyWrapper.str, keyWrapper.length);
|
||||
|
||||
retval[key] = xmlrpc_c::value(memberWrapper.valueP);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_nil::value_nil() {
|
||||
|
||||
class cWrapper {
|
||||
public:
|
||||
xmlrpc_value * valueP;
|
||||
|
||||
cWrapper() {
|
||||
xmlrpc_env env;
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
this->valueP = xmlrpc_nil_new(&env);
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
~cWrapper() {
|
||||
xmlrpc_DECREF(this->valueP);
|
||||
}
|
||||
};
|
||||
|
||||
cWrapper wrapper;
|
||||
|
||||
this->instantiate(wrapper.valueP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
value_nil::value_nil(xmlrpc_c::value const baseValue) {
|
||||
|
||||
if (baseValue.type() != xmlrpc_c::value::TYPE_NIL)
|
||||
throw(error("Not nil type. See type() method"));
|
||||
else {
|
||||
this->instantiate(baseValue.cValueP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
166
libs/xmlrpc-c/src/cpp/xml.cpp
Normal file
166
libs/xmlrpc-c/src/cpp/xml.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
#include <string>
|
||||
|
||||
#include "xmlrpc-c/girerr.hpp"
|
||||
using girerr::error;
|
||||
#include "xmlrpc-c/base.h"
|
||||
#include "xmlrpc-c/base_int.h"
|
||||
#include "xmlrpc-c/base.hpp"
|
||||
#include "xmlrpc-c/xml.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace xmlrpc_c;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class cValueWrapper {
|
||||
/*----------------------------------------------------------------------------
|
||||
Use an object of this class to set up to remove a reference to an
|
||||
xmlrpc_value object (a C object with manual reference management)
|
||||
at then end of a scope -- even if the scope ends with a throw.
|
||||
-----------------------------------------------------------------------------*/
|
||||
public:
|
||||
xmlrpc_value * valueP;
|
||||
cValueWrapper(xmlrpc_value * valueP) : valueP(valueP) {}
|
||||
~cValueWrapper() { xmlrpc_DECREF(valueP); }
|
||||
};
|
||||
|
||||
xmlrpc_value *
|
||||
cArrayFromParamList(paramList const& paramList) {
|
||||
|
||||
xmlrpc_env env;
|
||||
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
xmlrpc_value * paramArrayP;
|
||||
|
||||
paramArrayP = xmlrpc_array_new(&env);
|
||||
if (!env.fault_occurred) {
|
||||
for (unsigned int i = 0;
|
||||
i < paramList.size() && !env.fault_occurred;
|
||||
++i) {
|
||||
cValueWrapper const param(paramList[i].cValue());
|
||||
|
||||
xmlrpc_array_append_item(&env, paramArrayP, param.valueP);
|
||||
}
|
||||
}
|
||||
if (env.fault_occurred) {
|
||||
xmlrpc_DECREF(paramArrayP);
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
return paramArrayP;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
namespace xmlrpc_c {
|
||||
namespace xml {
|
||||
|
||||
|
||||
void
|
||||
generateCall(string const& methodName,
|
||||
paramList const& paramList,
|
||||
string * const callXmlP) {
|
||||
/*----------------------------------------------------------------------------
|
||||
Generate the XML for an XML-RPC call, given a method name and parameter
|
||||
list.
|
||||
-----------------------------------------------------------------------------*/
|
||||
class memblockWrapper {
|
||||
xmlrpc_mem_block * const memblockP;
|
||||
public:
|
||||
memblockWrapper(xmlrpc_mem_block * const memblockP) :
|
||||
memblockP(memblockP) {}
|
||||
|
||||
~memblockWrapper() {
|
||||
XMLRPC_MEMBLOCK_FREE(char, memblockP);
|
||||
}
|
||||
};
|
||||
|
||||
xmlrpc_mem_block * callXmlMP;
|
||||
xmlrpc_env env;
|
||||
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
callXmlMP = XMLRPC_MEMBLOCK_NEW(char, &env, 0);
|
||||
if (!env.fault_occurred) {
|
||||
memblockWrapper callXmlHolder(callXmlMP);
|
||||
// Makes callXmlMP get freed at end of scope
|
||||
|
||||
xmlrpc_value * const paramArrayP(cArrayFromParamList(paramList));
|
||||
|
||||
xmlrpc_serialize_call(&env, callXmlMP, methodName.c_str(),
|
||||
paramArrayP);
|
||||
|
||||
*callXmlP = string(XMLRPC_MEMBLOCK_CONTENTS(char, callXmlMP),
|
||||
XMLRPC_MEMBLOCK_SIZE(char, callXmlMP));
|
||||
|
||||
xmlrpc_DECREF(paramArrayP);
|
||||
}
|
||||
if (env.fault_occurred)
|
||||
throw(error(env.fault_string));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
parseResponse(string const& responseXml,
|
||||
rpcOutcome * const outcomeP) {
|
||||
/*----------------------------------------------------------------------------
|
||||
Parse the XML for an XML-RPC response into an XML-RPC result value.
|
||||
-----------------------------------------------------------------------------*/
|
||||
xmlrpc_env env;
|
||||
|
||||
xmlrpc_env_init(&env);
|
||||
|
||||
xmlrpc_value * c_resultP;
|
||||
|
||||
c_resultP =
|
||||
xmlrpc_parse_response(&env, responseXml.c_str(), responseXml.size());
|
||||
|
||||
/* Unfortunately, xmlrpc_parse_response() does not distinguish between
|
||||
unparseable XML and XML that cleanly indicates an RPC failure or
|
||||
other failure on the server end. We'll fix that some day, but for
|
||||
now, we just assume any failure is an XML-RPC RPC failure.
|
||||
*/
|
||||
if (env.fault_occurred)
|
||||
*outcomeP =
|
||||
rpcOutcome(fault(env.fault_string,
|
||||
static_cast<fault::code_t>(env.fault_code)));
|
||||
else {
|
||||
*outcomeP = rpcOutcome(value(c_resultP));
|
||||
xmlrpc_DECREF(c_resultP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
parseSuccessfulResponse(string const& responseXml,
|
||||
value * const resultP) {
|
||||
/*----------------------------------------------------------------------------
|
||||
Same as parseResponse(), but expects the response to indicate success;
|
||||
throws an error if it doesn't.
|
||||
-----------------------------------------------------------------------------*/
|
||||
rpcOutcome outcome;
|
||||
|
||||
parseResponse(responseXml, &outcome);
|
||||
|
||||
if (!outcome.succeeded())
|
||||
throw(error("RPC failed. " + outcome.getFault().getDescription()));
|
||||
|
||||
*resultP = outcome.getResult();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
trace(string const& label,
|
||||
string const& xml) {
|
||||
|
||||
xmlrpc_traceXml(label.c_str(), xml.c_str(), xml.size());
|
||||
|
||||
}
|
||||
|
||||
|
||||
}} // namespace
|
Reference in New Issue
Block a user