FS-2746 --resolve large xmlrpc update thanks garmt

This commit is contained in:
Jeff Lenk
2012-10-13 11:37:25 -05:00
parent 37ecad9903
commit 6b6c83a718
397 changed files with 41822 additions and 33841 deletions

View File

@@ -1,4 +0,0 @@
meerkat-app-list
xmlrpc_sample_add_server
xmlrpc_sample_add_client
sample_add_client_complex

View File

@@ -15,8 +15,8 @@ include $(BLDDIR)/config.mk
default: all
CXXFLAGS = $(CXXFLAGS_COMMON) $(CFLAGS_PERSONAL) $(CADD)
LDFLAGS = $(LADD)
CXXFLAGS = $(CFLAGS_PERSONAL) $(CADD)
LDFLAGS += $(LADD)
# If this were a real application, working from an installed copy of
# Xmlrpc-c, XMLRPC_C_CONFIG would just be 'xmlrpc-c-config'. It would be
@@ -24,10 +24,14 @@ LDFLAGS = $(LADD)
XMLRPC_C_CONFIG = $(BLDDIR)/xmlrpc-c-config.test
SERVERPROGS_CGI = \
xmlrpc_sample_add_server.cgi
SERVERPROGS_ABYSS = \
xmlrpc_inetd_server \
xmlrpc_loop_server \
xmlrpc_sample_add_server \
callinfo_abyss_server \
CLIENTPROGS = \
xmlrpc_sample_add_client \
@@ -45,7 +49,11 @@ ifeq ($(MUST_BUILD_CLIENT),yes)
PROGS += $(CLIENTPROGS)
endif
PROGS += pstream_inetd_server
ifeq ($(ENABLE_CGI_SERVER),yes)
PROGS += $(SERVERPROGS_CGI)
endif
PROGS += pstream_inetd_server pstream_serial_server
ifeq ($(MUST_BUILD_CLIENT),yes)
PROGS += pstream_client
@@ -53,37 +61,43 @@ endif
INCLUDES = -I. $(shell $(XMLRPC_C_CONFIG) c++2 client abyss-server --cflags)
LDADD_SERVER_ABYSS = \
$(shell $(XMLRPC_C_CONFIG) c++2 abyss-server --ldadd)
LIBS_SERVER_ABYSS = \
$(shell $(XMLRPC_C_CONFIG) c++2 abyss-server --libs)
LDADD_CLIENT = \
$(shell $(XMLRPC_C_CONFIG) c++2 client --ldadd)
LIBS_SERVER_CGI = \
$(shell $(XMLRPC_C_CONFIG) c++2 cgi-server --libs)
LDADD_BASE = \
$(shell $(XMLRPC_C_CONFIG) c++2 --ldadd)
LIBS_CLIENT = \
$(shell $(XMLRPC_C_CONFIG) c++2 client --libs)
LIBS_BASE = \
$(shell $(XMLRPC_C_CONFIG) c++2 --libs)
all: $(PROGS)
$(SERVERPROGS_CGI):%.cgi:%_cgi.o
$(CXXLD) -o $@ $^ $(LIBS_SERVER_CGI) $(LDFLAGS)
$(SERVERPROGS_ABYSS):%:%.o
$(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_SERVER_ABYSS)
$(CXXLD) -o $@ $^ $(LIBS_SERVER_ABYSS) $(LDFLAGS)
$(CLIENTPROGS):%:%.o
$(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_CLIENT)
$(CXXLD) -o $@ $^ $(LIBS_CLIENT) $(LDFLAGS)
LDADD_PSTREAM_CLIENT = \
$(shell $(XMLRPC_C_CONFIG) c++2 client --ldadd)
LIBS_PSTREAM_CLIENT = \
$(shell $(XMLRPC_C_CONFIG) c++2 client --libs)
pstream_client:%:%.o
$(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_PSTREAM_CLIENT)
$(CXXLD) -o $@ $^ $(LIBS_PSTREAM_CLIENT) $(LDFLAGS)
LDADD_PSTREAM_SERVER = \
$(shell $(XMLRPC_C_CONFIG) c++2 pstream-server --ldadd)
LIBS_PSTREAM_SERVER = \
$(shell $(XMLRPC_C_CONFIG) c++2 pstream-server --libs)
pstream_inetd_server:%:%.o
$(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_PSTREAM_SERVER)
pstream_inetd_server pstream_serial_server:%:%.o
$(CXXLD) -o $@ $^ $(LIBS_PSTREAM_SERVER) $(LDFLAGS)
OBJECTS = $(PROGS:%=%.o)
OBJECTS = $(patsubst %,%.o,$(patsubst %.cgi,%_cgi,$(PROGS)))
$(OBJECTS):%.o:%.cpp
$(CXX) -c $(INCLUDES) $(CXXFLAGS) $<
@@ -97,11 +111,9 @@ config.h:
xmlrpc_amconfig.h:
$(LN_S) $(BLDDIR)/$@ .
include $(SRCDIR)/common.mk
.PHONY: clean
clean: clean-common
rm -f $(PROGS) config.h xmlrpc_amconfig.h
clean:
rm -f $(PROGS) *.o config.h xmlrpc_amconfig.h
.PHONY: distclean
distclean: clean

View File

@@ -0,0 +1,133 @@
// A simple standalone XML-RPC server written in C++.
//
// This server returns to the caller his IP address and port number,
// as a demonstration of how to access such information.
//
// This works only on Unix (to wit, something that uses Abyss's
// ChanSwitchUnix channel switch to accept TCP connections from clients).
//
// See xmlrpc_sample_add_server.cpp for a more basic example.
//
// To run this:
//
// $ ./callinfo_abyss_server &
// $ xmlrpc localhost:8080 getCallInfo
#include <cassert>
#include <stdexcept>
#include <iostream>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/registry.hpp>
#include <xmlrpc-c/server_abyss.hpp>
#include <xmlrpc-c/abyss.h>
using namespace std;
struct tcpPortAddr {
unsigned char ipAddr[4];
unsigned short portNumber;
};
static struct tcpPortAddr
tcpAddrFromSockAddr(struct sockaddr const sockAddr) {
const struct sockaddr_in * const sockAddrInP(
static_cast<struct sockaddr_in *>((void *)&sockAddr));
const unsigned char * const ipAddr(
static_cast<const unsigned char *>(
(const void *)&sockAddrInP->sin_addr.s_addr)
); // 4 byte array
assert(sockAddrInP->sin_family == AF_INET);
struct tcpPortAddr retval;
retval.ipAddr[0] = ipAddr[0];
retval.ipAddr[1] = ipAddr[1];
retval.ipAddr[2] = ipAddr[2];
retval.ipAddr[3] = ipAddr[3];
retval.portNumber = ntohs(sockAddrInP->sin_port);
return retval;
}
static std::string
rpcIpAddrMsg(xmlrpc_c::callInfo_serverAbyss const& callInfo) {
void * chanInfoPtr;
SessionGetChannelInfo(callInfo.abyssSessionP, &chanInfoPtr);
struct abyss_unix_chaninfo * const chanInfoP(
static_cast<struct abyss_unix_chaninfo *>(chanInfoPtr));
struct tcpPortAddr const tcpAddr(tcpAddrFromSockAddr(chanInfoP->peerAddr));
char msg[128];
sprintf(msg, "RPC is from IP address %u.%u.%u.%u, Port %hu",
tcpAddr.ipAddr[0],
tcpAddr.ipAddr[1],
tcpAddr.ipAddr[2],
tcpAddr.ipAddr[3],
tcpAddr.portNumber);
return std::string(msg);
}
class getCallInfoMethod : public xmlrpc_c::method2 {
public:
void
execute(xmlrpc_c::paramList const& paramList,
const xmlrpc_c::callInfo * const callInfoPtr,
xmlrpc_c::value * const retvalP) {
const xmlrpc_c::callInfo_serverAbyss * const callInfoP(
dynamic_cast<const xmlrpc_c::callInfo_serverAbyss *>(callInfoPtr));
paramList.verifyEnd(0);
// Because this gets called via a xmlrpc_c::serverAbyss:
assert(callInfoP != NULL);
*retvalP = xmlrpc_c::value_string(rpcIpAddrMsg(*callInfoP));
}
};
int
main(int const,
const char ** const) {
try {
xmlrpc_c::registry myRegistry;
xmlrpc_c::methodPtr const getCallInfoMethodP(new getCallInfoMethod);
myRegistry.addMethod("getCallInfo", getCallInfoMethodP);
xmlrpc_c::serverAbyss myAbyssServer(xmlrpc_c::serverAbyss::constrOpt()
.registryP(&myRegistry)
.portNumber(8080)
);
myAbyssServer.run();
// xmlrpc_c::serverAbyss.run() never returns
assert(false);
} catch (exception const& e) {
cerr << "Something failed. " << e.what() << endl;
}
return 0;
}

View File

@@ -1,108 +0,0 @@
// List recently-released Linux applications. (Written in C++.)
// For more details about O'Reilly's excellent Meerkat news service, see:
// http://www.oreillynet.com/pub/a/rss/2000/11/14/meerkat_xmlrpc.html */
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
#include <xmlrpc-c/oldcppwrapper.hpp>
#define NAME "XML-RPC C++ Meerkat Query Demo"
#define VERSION "0.1"
#define MEERKAT_URL "http://www.oreillynet.com/meerkat/xml-rpc/server.php"
#define SOFTWARE_LINUX (6)
static void list_apps (int hours) {
// Build our time_period parameter.
ostringstream time_period_stream;
time_period_stream << hours << "HOUR";
string time_period = time_period_stream.str();
// Assemble our meerkat query recipe.
XmlRpcValue recipe = XmlRpcValue::makeStruct();
recipe.structSetValue("category", XmlRpcValue::makeInt(SOFTWARE_LINUX));
recipe.structSetValue("time_period", XmlRpcValue::makeString(time_period));
recipe.structSetValue("descriptions", XmlRpcValue::makeInt(76));
// Build our parameter array.
XmlRpcValue param_array = XmlRpcValue::makeArray();
param_array.arrayAppendItem(recipe);
// Create a client pointing to Meerkat.
XmlRpcClient meerkat (MEERKAT_URL);
// Perform the query.
XmlRpcValue apps = meerkat.call("meerkat.getItems", param_array);
// Print our results.
int first = 1;
size_t app_count = apps.arraySize();
for (size_t i = 0; i < app_count; i++) {
XmlRpcValue app = apps.arrayGetItem(i);
// Get some information about our application.
string title = app.structGetValue("title").getString();
string link = app.structGetValue("link").getString();
string description = app.structGetValue("description").getString();
// Print a separator line if necessary.
if (first)
first = 0;
else
cout << endl;
// Print this application entry.
if (description.size() > 0) {
cout << title << endl << description << endl << link << endl;
} else {
cout << title << endl << description << endl << link << endl;
}
}
}
// Print out a usage message.
static void usage (void)
{
cerr << "Usage: meekat-app-list [hours]" << endl;
cerr << "Data from <http://www.oreillynet.com/meerkat/>." << endl;
exit(1);
}
int main (int argc, char **argv) {
int status = 0;
int hours = 25;
// Parse our command-line arguments.
if (argc == 1) {
// Use default value for hours.
} else if (argc == 2) {
hours = atoi(argv[1]);
}
if (hours == 0)
usage();
if (hours > 49) {
cerr << "It's not nice to ask for > 49 hours at once." << endl;
exit(1);
}
// Start up our client library.
XmlRpcClient::Initialize(NAME, VERSION);
// Call our implementation, and watch out for faults.
try {
list_apps(hours);
} catch (XmlRpcFault& fault) {
cerr << argv[0] << ": XML-RPC fault #" << fault.getFaultCode()
<< ": " << fault.getFaultString() << endl;
status = 1;
}
// Shut down our client library.
XmlRpcClient::Terminate();
return status;
}

View File

@@ -25,7 +25,7 @@
#include <string>
#include <iostream>
#include <unistd.h>
#include <sys/signal.h>
#include <signal.h>
#include <xmlrpc-c/girerr.hpp>
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/client.hpp>

View File

@@ -22,7 +22,7 @@
#endif
#include <cassert>
#include <iostream>
#include <sys/signal.h>
#include <signal.h>
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/registry.hpp>
@@ -76,12 +76,7 @@ main(int const,
.socketFd(STDIN_FILENO)
.registryP(&myRegistry));
for (bool clientHasDisconnected = false; !clientHasDisconnected;)
server.runOnce(&clientHasDisconnected);
// This reads one packet (containing an XML-RPC call message)
// from Standard Input, executes the indicated RPC, and writes
// one packet containing the XML-RPC response message to
// Standard Input.
server.run();
} catch (exception const& e) {
cerr << "Something threw an error: " << e.what() << endl;

View File

@@ -0,0 +1,84 @@
/* A simple standalone RPC server based on an Xmlrpc-c packet socket.
This program expects the invoker to provide a socket in listen mode
as Standard Input.
This is not an XML-RPC server, because it uses a simple packet socket
instead of HTTP. See xmlrpc_sample_add_server.cpp for an example of
an XML-RPC server.
The advantage of this example over XML-RPC is that it has a connection
concept. The client can be connected indefinitely and the server gets
notified when the client terminates, even if it gets aborted by its OS.
Here's an example of running this:
$ socketexec -listen -local_port=8080 ./pstream_serial_server
*/
#ifndef WIN32
#include <unistd.h>
#endif
#include <cassert>
#include <iostream>
#include <signal.h>
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/registry.hpp>
#include <xmlrpc-c/server_pstream.hpp>
using namespace std;
class sampleAddMethod : public xmlrpc_c::method {
public:
sampleAddMethod() {
// signature and help strings are documentation -- the client
// can query this information with a system.methodSignature and
// system.methodHelp RPC.
this->_signature = "i:ii"; // method's arguments are two integers
this->_help = "This method adds two integers together";
}
void
execute(xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP) {
int const addend(paramList.getInt(0));
int const adder(paramList.getInt(1));
paramList.verifyEnd(2);
*retvalP = xmlrpc_c::value_int(addend + adder);
}
};
int
main(int const,
const char ** const) {
// It's a good idea to disable SIGPIPE signals; if client closes his end
// of the pipe/socket, we'd rather see a failure to send a response than
// get killed by the OS.
signal(SIGPIPE, SIG_IGN);
try {
xmlrpc_c::registry myRegistry;
xmlrpc_c::methodPtr const sampleAddMethodP(new sampleAddMethod);
myRegistry.addMethod("sample.add", sampleAddMethodP);
xmlrpc_c::serverPstream server(
xmlrpc_c::serverPstream::constrOpt()
.socketFd(STDIN_FILENO)
.registryP(&myRegistry));
server.runSerial();
} catch (exception const& e) {
cerr << "Something threw an error: " << e.what() << endl;
}
return 0;
}

View File

@@ -1,6 +1,25 @@
/* A simple XML-RPC server that runs under Inetd. I.e. it lets the invoking
program handle all the connection switching and simply processes one
RPC on the provided connection (Standard Input) and exits.
A typical example of where this would be useful is with an Inetd
"super server."
xmlrpc_sample_add_server.cpp is a server that does the same thing,
but you give it a TCP port number and it listens for TCP connections
and processes RPCs ad infinitum. xmlrpc_socket_server.c is halfway
in between those -- you give it an already bound and listening
socket, and it listens for TCP connections and processes RPCs ad
infinitum.
Here is an easy way to test this program:
socketexec --accept --local_port=8080 --stdin -- ./xmlrpc_inetd_server
Now run the client program 'xmlrpc_sample_add_client'. Socketexec
will accept the connection that the client program requests and pass it
to this program on Standard Input. This program will perform the RPC,
respond to the client, then exit.
*/
#ifndef WIN32
@@ -49,10 +68,8 @@ main(int const,
myRegistry.addMethod("sample.add", sampleAddMethodP);
xmlrpc_c::serverAbyss myAbyssServer(
myRegistry,
8080, // TCP port on which to listen
"/tmp/xmlrpc_log" // Log file
);
xmlrpc_c::serverAbyss::constrOpt()
.registryP(&myRegistry));
myAbyssServer.runConn(STDIN_FILENO);
/* This reads the HTTP POST request from Standard Input and

View File

@@ -62,10 +62,9 @@ main(int const,
myRegistry.addMethod("sample.add", sampleAddMethodP);
xmlrpc_c::serverAbyss myAbyssServer(
myRegistry,
8080, // TCP port on which to listen
"/tmp/xmlrpc_log" // Log file
);
xmlrpc_c::serverAbyss::constrOpt()
.registryP(&myRegistry)
.portNumber(8080));
myAbyssServer.run();
// xmlrpc_c::serverAbyss.run() never returns

View File

@@ -0,0 +1,62 @@
/* A CGI script that effects a simple XML-RPC server, written in C++.
See the identically named C program source code for hints on running
this example.
*/
#include <cassert>
#include <iostream>
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/registry.hpp>
#include <xmlrpc-c/server_cgi.hpp>
using namespace std;
class sampleAddMethod : public xmlrpc_c::method {
public:
sampleAddMethod() {
// signature and help strings are documentation -- the client
// can query this information with a system.methodSignature and
// system.methodHelp RPC.
this->_signature = "i:ii"; // method's arguments, result are integers
this->_help = "This method adds two integers together";
}
void
execute(xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP) {
int const addend(paramList.getInt(0));
int const adder(paramList.getInt(1));
paramList.verifyEnd(2);
*retvalP = xmlrpc_c::value_int(addend + adder);
}
};
int
main(int const,
const char ** const) {
try {
xmlrpc_c::registry myRegistry;
xmlrpc_c::methodPtr const sampleAddMethodP(new sampleAddMethod);
myRegistry.addMethod("sample.add", sampleAddMethodP);
xmlrpc_c::serverCgi myServer(
xmlrpc_c::serverCgi::constrOpt()
.registryP(&myRegistry));
myServer.processCall();
} catch (exception const& e) {
cerr << "Something failed. " << e.what() << endl;
}
return 0;
}