git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@8545 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Michael Jerris
2008-05-23 20:56:24 +00:00
parent d2290cfa3a
commit 00654d880e
338 changed files with 55725 additions and 19400 deletions

View File

@@ -5,33 +5,34 @@
# these programs depend.
ifeq ($(SRCDIR)x,x)
ifeq ($(SRCDIR),)
SRCDIR = $(CURDIR)/../..
BUILDDIR = $(SRCDIR)
BLDDIR = $(SRCDIR)
endif
SUBDIR=examples/cpp
include $(BLDDIR)/config.mk
default: all
include $(BUILDDIR)/Makefile.config
CXXFLAGS = $(CXXFLAGS_COMMON) $(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
# found in the user's PATH.
XMLRPC_C_CONFIG = $(BUILDDIR)/xmlrpc-c-config.test
XMLRPC_C_CONFIG = $(BLDDIR)/xmlrpc-c-config.test
SERVERPROGS_ABYSS = \
xmlrpc_inetd_server \
xmlrpc_loop_server \
xmlrpc_sample_add_server \
LEGACY_CLIENTPROGS = \
meerkat-app-list
CLIENTPROGS = \
xmlrpc_sample_add_client \
sample_add_client_complex \
asynch_client \
# Build up PROGS:
PROGS =
@@ -41,10 +42,16 @@ ifeq ($(ENABLE_ABYSS_SERVER),yes)
endif
ifeq ($(MUST_BUILD_CLIENT),yes)
PROGS += $(CLIENTPROGS) $(LEGACY_CLIENTPROGS)
PROGS += $(CLIENTPROGS)
endif
INCLUDES = $(shell $(XMLRPC_C_CONFIG) c++2 client abyss-server --cflags)
PROGS += pstream_inetd_server
ifeq ($(MUST_BUILD_CLIENT),yes)
PROGS += pstream_client
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)
@@ -55,31 +62,42 @@ LDADD_CLIENT = \
LDADD_BASE = \
$(shell $(XMLRPC_C_CONFIG) c++2 --ldadd)
LDADD_LEGACY_CLIENT = \
$(shell $(XMLRPC_C_CONFIG) c++ client --ldadd)
all: $(PROGS)
$(SERVERPROGS_ABYSS):%:%.o
$(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_SERVER_ABYSS)
$(LEGACY_CLIENTPROGS):%:%.o
$(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_LEGACY_CLIENT)
$(CLIENTPROGS):%:%.o
$(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_CLIENT)
%.o:%.cpp
LDADD_PSTREAM_CLIENT = \
$(shell $(XMLRPC_C_CONFIG) c++2 client --ldadd)
pstream_client:%:%.o
$(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_PSTREAM_CLIENT)
LDADD_PSTREAM_SERVER = \
$(shell $(XMLRPC_C_CONFIG) c++2 pstream-server --ldadd)
pstream_inetd_server:%:%.o
$(CXXLD) -o $@ $(LDFLAGS) $^ $(LDADD_PSTREAM_SERVER)
OBJECTS = $(PROGS:%=%.o)
$(OBJECTS):%.o:%.cpp
$(CXX) -c $(INCLUDES) $(CXXFLAGS) $<
*.c: config.h xmlrpc_amconfig.h
# See example/Makefile for an explanation of config.h and xmlrpc_amconfig.h
$(OBJECTS): config.h xmlrpc_amconfig.h
config.h:
$(LN_S) $(BUILDDIR)/xmlrpc_config.h $@
$(LN_S) $(BLDDIR)/xmlrpc_config.h $@
xmlrpc_amconfig.h:
$(LN_S) $(BUILDDIR)/$@ .
$(LN_S) $(BLDDIR)/$@ .
include $(SRCDIR)/Makefile.common
include $(SRCDIR)/common.mk
.PHONY: clean
clean: clean-common

View File

@@ -0,0 +1,75 @@
/*=============================================================================
asynch_client.cpp
===============================================================================
This is an example of an XML-RPC client that uses XML-RPC for C/C++
(Xmlrpc-c).
In particular, it does multiple RPCs asynchronously, running
simultaneously.
=============================================================================*/
#include <cassert>
#include <cstdlib>
#include <string>
#include <iostream>
#include <xmlrpc-c/girerr.hpp>
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/client.hpp>
using namespace std;
int
main(int argc, char **) {
if (argc-1 > 0) {
cerr << "This program has no arguments" << endl;
exit(1);
}
try {
xmlrpc_c::clientXmlTransport_curl myTransport;
xmlrpc_c::client_xml myClient(&myTransport);
string const methodName("sample.add");
xmlrpc_c::paramList sampleAddParms1;
sampleAddParms1.add(xmlrpc_c::value_int(3));
sampleAddParms1.add(xmlrpc_c::value_int(1));
xmlrpc_c::rpcPtr rpc1P(methodName, sampleAddParms1);
xmlrpc_c::paramList sampleAddParms2;
sampleAddParms2.add(xmlrpc_c::value_int(5));
sampleAddParms2.add(xmlrpc_c::value_int(7));
xmlrpc_c::rpcPtr rpc2P(methodName, sampleAddParms2);
string const serverUrl("http://localhost:8080/RPC2");
xmlrpc_c::carriageParm_curl0 myCarriageParm(serverUrl);
rpc1P->start(&myClient, &myCarriageParm);
rpc2P->start(&myClient, &myCarriageParm);
cout << "Two RPCs started. Waiting for them to finish." << endl;
myClient.finishAsync(xmlrpc_c::timeout()); // infinite timeout
assert(rpc1P->isFinished());
assert(rpc2P->isFinished());
int const sum1(xmlrpc_c::value_int(rpc1P->getResult()));
int const sum2(xmlrpc_c::value_int(rpc2P->getResult()));
cout << "Result of RPC 1 (sum of 3 and 1): " << sum1 << endl;
cout << "Result of RPC 2 (sum of 5 and 7): " << sum2 << endl;
} catch (exception const& e) {
cerr << "Client threw error: " << e.what() << endl;
} catch (...) {
cerr << "Client threw unexpected error." << endl;
}
return 0;
}

View File

@@ -0,0 +1,84 @@
/*=============================================================================
pstream_client.cpp
===============================================================================
This is an example of a client that uses XML-RPC for C/C++
(Xmlrpc-c).
In particular, it uses the simple "packet stream" XML transport mechanism
instead of HTTP as specified by XML-RPC (so this is not an XML-RPC
client).
You have to supply as Standard Input a stream (TCP) socket whose other
end is hooked up to the RPC server. The 'socket_exec' program is a
good way to arrange that.
The sample program pstream_server.cpp is compatible with this client.
Example:
$ socketexec -connect -remote_host=localhost -remote_port=8080 \
./pstream_client
=============================================================================*/
#include <cassert>
#include <cstdlib>
#include <string>
#include <iostream>
#include <unistd.h>
#include <sys/signal.h>
#include <xmlrpc-c/girerr.hpp>
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/client.hpp>
#include <xmlrpc-c/client_transport.hpp>
using namespace std;
int
main(int argc, char **) {
if (argc-1 > 0) {
cerr << "This program has no arguments" << endl;
exit(1);
}
// It's a good idea to disable SIGPIPE signals; if server closes his end
// of the pipe/socket, we'd rather see a failure to send a call than
// get killed by the OS.
signal(SIGPIPE, SIG_IGN);
try {
xmlrpc_c::clientXmlTransport_pstream myTransport(
xmlrpc_c::clientXmlTransport_pstream::constrOpt()
.fd(STDIN_FILENO));
xmlrpc_c::client_xml myClient(&myTransport);
string const methodName("sample.add");
xmlrpc_c::paramList sampleAddParms;
sampleAddParms.add(xmlrpc_c::value_int(5));
sampleAddParms.add(xmlrpc_c::value_int(7));
xmlrpc_c::rpcPtr myRpcP(methodName, sampleAddParms);
xmlrpc_c::carriageParm_pstream myCarriageParm;
// Empty; transport doesn't need any information
myRpcP->call(&myClient, &myCarriageParm);
assert(myRpcP->isFinished());
int const sum(xmlrpc_c::value_int(myRpcP->getResult()));
// Assume the method returned an integer; throws error if not
cout << "Result of RPC (sum of 5 and 7): " << sum << endl;
} catch (exception const& e) {
cerr << "Client threw error: " << e.what() << endl;
} catch (...) {
cerr << "Client threw unexpected error." << endl;
}
return 0;
}

View File

@@ -0,0 +1,90 @@
/* A simple standalone RPC server based on an Xmlrpc-c packet socket.
This program expects the invoker to provide an established connection
to a client as Standard Input (E.g. Inetd can do this). It processes
RPCs from that connection until the client closes the connection.
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 -accept -local_port=8080 ./pstream_inetd_server
*/
#ifndef WIN32
#include <unistd.h>
#endif
#include <cassert>
#include <iostream>
#include <sys/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::serverPstreamConn server(
xmlrpc_c::serverPstreamConn::constrOpt()
.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.
} catch (exception const& e) {
cerr << "Something threw an error: " << e.what() << endl;
}
return 0;
}

View File

@@ -14,12 +14,13 @@
facility. It is for demonstration purposes.
=============================================================================*/
#include <cassert>
#include <cstdlib>
#include <string>
#include <iostream>
#include <xmlrpc-c/girerr.hpp>
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/client.hpp>
#include <cassert>
using namespace std;
@@ -32,7 +33,11 @@ main(int argc, char **) {
}
try {
xmlrpc_c::clientXmlTransport_curl myTransport;
xmlrpc_c::clientXmlTransport_curl myTransport(
xmlrpc_c::clientXmlTransport_curl::constrOpt()
.no_ssl_verifyhost(true)
.user_agent("sample_add/1.0"));
xmlrpc_c::client_xml myClient(&myTransport);
string const methodName("sample.add");
@@ -47,8 +52,6 @@ main(int argc, char **) {
xmlrpc_c::carriageParm_curl0 myCarriageParm(serverUrl);
xmlrpc_c::value result;
myRpcP->call(&myClient, &myCarriageParm);
assert(myRpcP->isFinished());
@@ -58,8 +61,8 @@ main(int argc, char **) {
cout << "Result of RPC (sum of 5 and 7): " << sum << endl;
} catch (girerr::error const error) {
cerr << "Client threw error: " << error.what() << endl;
} catch (exception const& e) {
cerr << "Client threw error: " << e.what() << endl;
} catch (...) {
cerr << "Client threw unexpected error." << endl;
}

View File

@@ -0,0 +1,62 @@
/* 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.
*/
#ifndef WIN32
#include <unistd.h>
#endif
#include <cassert>
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/registry.hpp>
#include <xmlrpc-c/server_abyss.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) {
xmlrpc_c::registry myRegistry;
xmlrpc_c::methodPtr const sampleAddMethodP(new sampleAddMethod);
myRegistry.addMethod("sample.add", sampleAddMethodP);
xmlrpc_c::serverAbyss myAbyssServer(
myRegistry,
8080, // TCP port on which to listen
"/tmp/xmlrpc_log" // Log file
);
myAbyssServer.runConn(STDIN_FILENO);
/* This reads the HTTP POST request from Standard Input and
executes the indicated RPC.
*/
return 0;
}

View File

@@ -0,0 +1,72 @@
/* A simple standalone XML-RPC server based on Abyss that contains a
simple one-thread request processing loop.
xmlrpc_sample_add_server.cpp is a server that does the same thing, but
does it by running a full Abyss daemon in the background, so it has
less control over how the requests are served.
*/
#include <cassert>
#include <iostream>
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/registry.hpp>
#include <xmlrpc-c/server_abyss.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::serverAbyss myAbyssServer(
xmlrpc_c::serverAbyss::constrOpt()
.registryP(&myRegistry)
.portNumber(8080)
.logFileName("/tmp/xmlrpc_log"));
while (true) {
cout << "Waiting for next RPC..." << endl;
myAbyssServer.runOnce();
/* This waits for the next connection, accepts it, reads the
HTTP POST request, executes the indicated RPC, and closes
the connection.
*/
}
} catch (exception const& e) {
cerr << "Something failed. " << e.what() << endl;
}
return 0;
}

View File

@@ -1,3 +1,4 @@
#include <cstdlib>
#include <string>
#include <iostream>
#include <xmlrpc-c/girerr.hpp>
@@ -28,8 +29,8 @@ main(int argc, char **) {
cout << "Result of RPC (sum of 5 and 7): " << sum << endl;
} catch (girerr::error const error) {
cerr << "Client threw error: " << error.what() << endl;
} catch (exception const& e) {
cerr << "Client threw error: " << e.what() << endl;
} catch (...) {
cerr << "Client threw unexpected error." << endl;
}

View File

@@ -1,4 +1,11 @@
#include <cassert>
#include <stdexcept>
#include <iostream>
#ifdef WIN32
# include <windows.h>
#else
# include <unistd.h>
#endif
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/registry.hpp>
@@ -6,6 +13,13 @@
using namespace std;
#ifdef WIN32
#define SLEEP(seconds) SleepEx(seconds * 1000);
#else
#define SLEEP(seconds) sleep(seconds);
#endif
class sampleAddMethod : public xmlrpc_c::method {
public:
sampleAddMethod() {
@@ -26,6 +40,11 @@ public:
paramList.verifyEnd(2);
*retvalP = xmlrpc_c::value_int(addend + adder);
// Sometimes, make it look hard (so client can see what it's like
// to do an RPC that takes a while).
if (adder == 1)
SLEEP(2);
}
};
@@ -35,21 +54,24 @@ int
main(int const,
const char ** const) {
xmlrpc_c::registry myRegistry;
try {
xmlrpc_c::registry myRegistry;
xmlrpc_c::methodPtr const sampleAddMethodP(new sampleAddMethod);
myRegistry.addMethod("sample.add", sampleAddMethodP);
xmlrpc_c::serverAbyss myAbyssServer(
myRegistry,
8080, // TCP port on which to listen
"/tmp/xmlrpc_log" // Log file
);
myAbyssServer.run();
// xmlrpc_c::serverAbyss.run() never returns
assert(false);
xmlrpc_c::methodPtr const sampleAddMethodP(new sampleAddMethod);
myRegistry.addMethod("sample.add", sampleAddMethodP);
xmlrpc_c::serverAbyss myAbyssServer(
myRegistry,
8080, // TCP port on which to listen
"/tmp/xmlrpc_log" // Log file
);
myAbyssServer.run();
// xmlrpc_c::serverAbyss.run() never returns
assert(false);
} catch (exception const& e) {
cerr << "Something failed. " << e.what() << endl;
}
return 0;
}