This chapter describes the functions in the libxmlrpc_server function library, which is part of XML-RPC For C/C++ (Xmlrpc-c). Also see General Library Information - C
You must know something about XML-RPC (the protocol) to understand this chapter. You don't have to know the details of the protocol, since Xmlrpc-c is meant to spare you from learning that, but you do have to know the kinds of things that make up an XML-RPC transaction.
Everything you need to know about XML-RPC is here.
The libxmlrpc_server library provides functions for use in a program that is an XML-RPC server. These functions by themselves are not enough to implement a server; you need other facilities to do the bulk of the work, such as libxmlrpc_server_abyss. libxmlrpc_server contains only facilities that are common to multiple kinds of server implementations.
When using libxmlrpc_server, you must also use the libxmlrpc library. It contains additional facilities that an XML-RPC server needs but are general to XML-RPC and not specific to XML-RPC servers. Besides, the libxmlrpc_server library routines depend on it.
The xmlrpc_server.h header file declares the interface to libxmlrpc_server.
You'll have to figure out where on your system this file lives and how to make your compiler look there for it. Or use xmlrpc-c-config.
Because the libxmlrpc library is a prerequisite, you'll also need its header file (libxmlrpc.h).
The classic Unix name for the file containing the libxmlrpc_server library is libxmlrpc_server.a or libxmlrpc_server.so. The classic linker option to cause the library to be linked into your program is -l xmlrpc_server. These are hints; you'll have to modify this according to conventions of your particular platform. You'll also have to figure out where the library resides and how to make your linker look there for it. Or use xmlrpc-c-config.
The following libraries are prerequisites of libxmlrpc_server, so you'll need to link them in too:
A complete example of an XML-RPC server program that uses libxmlrpc_server is here.
An XML-RPC server consists of 1) machinery to receive XML-RPC calls and send responses to them (called the XML-RPC protocol driver) and 2) methods. The protocol driver can be constant for various XML-RPC server applications. It's the methods that make a particular XML-RPC server what it is. In the small example server mentioned above, which provides the service of adding two numbers together, libxmlrpc_server_abyss and an Abyss http server provide the protocol driver, and the "sample_add" method code is what makes it an addition server.
libxmlrpc_server provides a facility to connect the XML-RPC protocol driver with the methods. It is called the method registry. It forms a uniform interface that all methods can use to interact with all protocol drivers.
The essential structure of an Xmlrpc-c server program is like this: The program contains code for each of a bunch of methods. The program creates a method registry and adds each of its methods to the registry. The program then starts up a protocol driver and passes to it the full registry.
The protocol driver executes an XML-RPC call through the method registry. It passes the XML for the XML-RPC call to the method registry, and the method registry executes the appropriate registered method and returns the XML for the XML-RPC response to the protocol driver.
You implement a method as a C function, a pointer to which you register with the method in the method registry.
There are two types of method functions, an old one called Type 1 and a newer one called Type 2. The difference is that the Type 2 method function gets more information in its arguments. New code should use Type 2.
A Type 2 method function must have the following prototype:
xmlrpc_value *
mymethod(xmlrpc_env * envP,
xmlrpc_value * paramArrayP,
void * serverInfo,
void * callInfo);
Type 1 is the same except the callInfo argument is missing.
envP is an error environment variable pointer. You return in this variable the completion status of the method. It comes pre-initialized to a valid state that indicates no error has occurred. You need set it only if an error occurs. The method registry uses the information from this as the fault information in the XML-RPC response.
paramArrayP gives you the parameters of the XML-RPC call as an XML-RPC value. This value is an array with one element per parameter, in order. It might be an empty array. Note that each parameter may be a structure or array itself. It is a historical mistake that *paramArrayP is a xmlrpc_value type (at one time, the xmlrpc_value type was meant to be a general purpose data structure -- an extension to the C language, rather than just an entity for XML-RPC use). Do not let that fool you into thinking that the parameter of the RPC is an array. In XML-RPC, an RPC takes any number of parameters, and the elements of this array are those parameters.
The caller (the method registry) naturally provides a reference to the parameter xmlrpc_values to cover the method function's use of them. The caller releases such references after the method function returns.
The XML-RPC caller (the XML-RPC client) determines what form of parameters you get. Unlike most programming languages, Xmlrpc-c (and XML-RPC) give the method writer no way to insist that parameters arrive in a certain form. For example, a method that adds two integers together might receive as parameters 3 strings and an array of date/times from a confused client. So the method has to check its parameter types.
But the client has no control over the fact that paramArrayP points to an array. That's part of the Xmlrpc-c method registry.
serverInfo is a pointer to a data structure that gives some information about the server that is calling the method function. It is always the same for a particular method for the life of a server. It is opaque to Xmlrpc-c. It is a value that the server registers for the method as part of starting up the server.
If the registry does not contain any server information for the method (the code that registered the method didn't provide any), serverInfo is a null pointer.
The sample add server doesn't even use serverInfo, but here is an example of how a variation on that server might use it: Let's say you want the sample add server to keep a log of all the sums it reports, for legal purposes. So at startup time, the server opens a log file. It puts the file descriptor in a "struct sumlog" structure and registers a pointer to that structure with the sample_add method as its server context. Now, when the server is running, every time the method function runs, it gets that pointer. It uses it to get the file descriptor, and uses that to record the sum that it computes.
WARNING: Some HTTP servers, and therefore any XML-RPC server based on one of them, use multiple processes to handle incoming connections. Some forms of XML-RPC servers based on libxmlrpc_server_abyss do. When this is the case, serverInfo does not point to the same memory as it did in the process that registered the method. It will normally be a copy of that memory, though, so if you regard it as read-only after you register the method, it is still useful.
callInfo is a pointer to non-XML-RPC information about the XML-RPC call. The server supplies callInfo when it calls the registry to process the XML-RPC call, such as with xmlrpc_registry_process_call2(). The server doesn't have to supply a value for this (old servers couldn't if they wanted to). If it doesn't, the method function gets a null pointer.
The value pointed to by callInfo is opaque to the registry; its meaning is entirely dependent upon the kind of server, so to use it, your method handler function must know what kind of server is calling it. For example, for an Abyss server, it is an Abyss session handle (type TSession *), which the method function can use to get information from the Abyss server about how the XML-RPC call arrived. In particular, Abyss can typically tell you the IP address and TCP port number of the client. See Request Handler Services in the Abyss manual.
See the documentation of the XML-RPC server that uses the registry for an explanation of callInfo.
The return value is meaningful only when the value you return via envP indicates success. The return value is a pointer to an XML-RPC value which is the result value of the RPC. The method registry puts this in the XML-RPC response. You must return the value with one reference on it to cover the caller's use of it. The caller (method registry) releases the reference when it is done with it. If you return failure (via envP, the caller ignores the return value, so be sure you don't add any references to anything for the caller.
static xmlrpc_value *
sample_add(xmlrpc_env * const envP,
xmlrpc_value * const paramArrayP,
void * const serverInfo) {
xmlrpc_int32 x, y, z;
/* Parse our argument array. */
xmlrpc_parse_value(envP, paramArrayP, "(ii)", &x, &y);
if (envP->fault_occurred)
return NULL;
/* Add our two numbers. */
z = x + y;
/* Return our result. */
return xmlrpc_build_value(envP, "i", z);
}
When the client specifies a method name that is not in the method registry, the method registry calls the "default method function" that you registered. A registry contains zero or one default method function. You can use this to bypass much of the work that the registry does and do your own dispatching of methods: just don't register any methods, and all XML-RPC calls will result in a call to your default method function.
If you don't register a default method function and an XML-RPC call specifies a method name that is not in the registry, the registry services automatically return a "no such method" fault response.
A default method function has the following prototype:
xmlrpc_value *
my_default_method(xmlrpc_env * envP,
const char * host,
const char * methodName,
xmlrpc_value * paramArrayP,
void * serverInfo);
envP, paramArrayP, and serverInfo are the same as for the regular method function (above).
methodName is the method name the client specified in the XML-RPC call. It is a UTF-8 NUL-terminated string, in the case (upper/lower) specified in the XML-RPC call.
host is meaningless. See xmlrpc_registry_add_method2() for an explanation of the history of this argument.
The interface is otherwise analogous to that for the regular method function (above).
The registry itself has type xmlrpc_registry.
There is one registry per XML-RPC server.
You create a registry with xmlrpc_registry_new() and destroy one with xmlrpc_registry_free().
You can create a method in the registry by calling xmlrpc_registry_add_method3(). Call this once for each method your server is to have.
The slightly more complex xmlrpc_registry_add_method_w_doc is the same as xmlrpc_registry_add_method() except that it has additional arguments for you to specify documentation of the method. The registry uses this documentation to implement the introspection system methods.
This function adds a method to a registry.
Example:
xmlrpc_registry * registryP;
xmlrpc_method2 method;
...
struct xmlrpc_method_info3 const methodInfo = {
.methodName = "sample.add",
.methodFunction = &sample_add,
};
xmlrpc_registry_add_method3(&env, registryP, &methodInfo);
The prototype is as follows:
typedef xmlrpc_value *
(*xmlrpc_method2)(xmlrpc_env * const envP,
xmlrpc_value * const paramArrayP,
void * const serverInfo,
void * const callInfo);
struct xmlrpc_method_info3 {
const char * methodName;
xmlrpc_method2 methodFunction;
void * serverInfo;
size_t stackSize;
const char * signatureString;
const char * help;
};
void
xmlrpc_registry_add_method3(
xmlrpc_env * const envP,
xmlrpc_registry * const registryP,
const struct xmlrpc_method_info3 * const infoP);
envP is an error environment variable pointer.
registryP identifies the registry to which you are adding the method (you must have created it with xmlrpc_registry_new()).
infoP points to a structure of information about the method you're adding. The structure has no higher meaning -- it is just a convenient way to pass arguments to xmlrpc_registry_add_method3. It is designed so that the value that means "not present" for any optional member is represented as zero bits.
Zero means you don't know, which causes xmlrpc_registry_add_method3() to assume 128K.
The string looks something like this example:
i:iii,s:
.
It is a list of signature strings, separated by commas. In the example, there
are two signatures:
i:iii
s:
Each signature string describes one form of calling the method. A signature string has the form:
<resultType>:<1stParmType><2ndParmType>...
resultType and xxxParmType are one character, corresponding to the type given here by the XML element name:
Note that there is no way to describe the specific contents of a struct or array.
Note that XML-RPC method always has exactly one return value, so there is always one character followed by a colon (:). An XML-RPC method can have any number of parameters, including zero, so there can be any number of characters, including zero, after the colon.
To decline to state the signatures, use a null pointer for signature. If you do that, system.MethodSignature will return a special response that says, "I frankly have no idea."
A signature list of "?" is equivalent to a null pointer and before Xmlrpc-c 1.05 (March 2006), that was the only way. But it is deprecated now.
This function was new in Xmlrpc-c 1.16 (September 2008). In older Xmlrpc-c, use xmlrpc_registry_add_method2() instead.
This function adds a method to a registry.
This function is obsolete; use xmlrpc_registry_add_method3() if possible.
The prototype is as follows:
void
xmlrpc_registry_add_method2(xmlrpc_env * envP,
xmlrpc_registry * registryP,
const char * methodName,
xmlrpc_method methodFunction,
const char * signature,
const char * help,
void * serverInfo);
envP and registryP arguments are analogous to the corresponding arguments of xmlrpc_registry_add_method3(). The remaining arguments are analogous to the like-named members of the struct xmlrpc_method_info3 which is an argument to xmlrpc_registry_add_method3().
This function was new in Xmlrpc-c 1.07 (October 2006). In older Xmlrpc-c, use xmlrpc_registry_add_method_w_doc instead.
This function adds a method to a registry.
This function is obsolete; use xmlrpc_registry_add_method3() instead if possible.
The prototype is as follows:
void
xmlrpc_registry_add_method(xmlrpc_env * envP,
xmlrpc_registry * registryP,
const char * host,
const char * methodName,
xmlrpc_method methodFunction,
void * serverInfo);
Arguments have the same meaning as the identically named arguments of xmlrpc_registry_add_method2().
host is meaningless. (It was once planned to be used so that a single registry could contain separate methods for separate hosts. Note that an HTTP server (and thus an XML-RPC server) can serve multiple hosts, each of which has a unique host name, such as "xmlrpc_1.giraffe-data.com". But current strategy is to handle multiple hosts by having a separate registry for each one. However, nothing for distinguishing multiple hosts exists today).
This function adds a method to a registry. It is just like xmlrpc_registry_add_method2() except that it registers a Type 1 handler, whereas the latter registers a Type 2 handler.
This function is obsolete; use xmlrpc_registry_add_method3() instead if possible
The prototype is as follows:
void
xmlrpc_registry_add_method_w_doc(xmlrpc_env * envP,
xmlrpc_registry * registryP,
const char * host,
const char * methodName,
xmlrpc_method methodFunction,
void * serverInfo,
const char * signature,
const char * help);
The arguments mean the same as for xmlrpc_registry_add_method2() and xmlrpc_registry_add_method()
typedef xmlrpc_value *
(*xmlrpc_default_method)(xmlrpc_env * envP,
const char * callInfoP,
const char * methodName,
xmlrpc_value * paramArrayP,
void * serverInfo);
void
xmlrpc_registry_set_default_method(xmlrpc_env * envP,
xmlrpc_registry * registryP,
xmlrpc_default_method handler,
void * serverInfo);
This function registers a default method function. A registry can have at most one default method function. If one is already registered, xmlrpc_registry_set_default_method() fails.
The function is analogous to that of xmlrpc_registry_add_method().
This function modifies the registry so that the built in introspection system methods do not exist, as they do by default.
There is no way to reverse this.
Example:
xmlrpc_env env;
xmlrpc_registry * const registryP = xmlrpc_registry_new(&env);
xmlrpc_registry_disable_introspection(registryP);
This function modifies the registry to set the shutdown function. By default, a registry has no shutdown function, which means it has no way to shut down the server. In particular, the system.shutdown system method always fails.
There is no way to reverse this.
Example:
static xmlrpc_server_shutdown_fn requestShutdown;
static void
requestShutdown(xmlrpc_env * const faultP,
void * const context,
const char * const comment,
void * const callInfo) {
int * const terminationRequestedP = context;
xmlrpc_env_init(faultP);
fprintf(stderr, "Termination requested: %s\n", comment);
*terminationRequestedP = 1;
}
...
{
xmlrpc_env env;
int terminationRequested;
xmlrpc_registry * const registryP = xmlrpc_registry_new(&env);
xmlrpc_set_shutdown(registryP, &requestShutdown, &terminationRequested);
...
}
Protoype:
void
xmlrpc_registry_set_shutdown(xmlrpc_registry * const registryP,
xmlrpc_server_shutdown_fn * const shutdownFn,
void * const context);
registryP identifies the registry in which you're setting the shutdown function.
shutdownFn is a function pointer to the function.
context is a value that has meaning to the shutdown function, but is opaque to Xmlrpc-c.
When the registry wants to shut down the server (to wit, when it processes a system.shutdown RPC), it calls the shutdown function. The arguments to the shutdown function are:
Note that this is not a regular error environment variable; it does not tell the caller of the function whether the function did what it was asked to do; refusing to shut down for a good reason is considered a successful execution of the shutdown function, and there is in fact no way for a shutdown function to report that it failed. A practical difference between this argument and regular error environment variable is that it is not an input to the shutdown function. You must always initialize the variable (with xmlrpc_env_init()).
That means, in the typical case, it's an Abyss session handle (type TSession *), and you can use it to find out the IP address and port number of the requester and possibly determine whether the requester has permission to shut down the server.
Before Xmlrpc-c 1.07 (October 2006), this argument is not present; there are only 3 arguments.
Note that once you've set a shutdown function, anyone who can get an XML-RPC call to your server can cause it to run. So if you don't want just anyone to be able to shut down your server, your shutdown function must do some kind of permission check.
This function modifies the registry to set the dialect for responses. By default (if you have never set the dialect), when an XML-RPC server executes an XML-RPC method via the registry, the response goes in the i8 dialect.
Example:
xmlrpc_env env;
xmlrpc_registry * const registryP = xmlrpc_registry_new(&env);
xmlrpc_registry_set_dialect(&env, registryP, xmlrpc_dialect_apache);
Protoype:
void
xmlrpc_registry_set_dialect(xmlrpc_env * const envP,
xmlrpc_registry * const registryP,
xmlrpc_dialect const dialect);
registryP identifies the registry in which you're setting the dialect.
dialect is the dialect you're setting.
This function was new in Xmlrpc-c 1.11 (June 2007). Before that, responses sent via the registry are always in the i8 dialect.
There are some methods, called system methods, that the registry implements internally (I.e. you don't use xmlrpc_registry_add_method to add one). A system method is concerned with the basic operation of the server rather than whatever job the particular server does.
libxmlrpc_server provides system methods to implement the XML-RPC Introspection facility. This facility is a standard set of methods that are defined to return information about the server that runs them. In particular, they return a list of all the methods the server implements and information about them.
If you consider introspection an unacceptable invasion of privacy, you can disable introspection by calling xmlrpc_registry_disable_introspection(). Then the server will not have those methods. In a new registry, introspection is enabled.
The introspection methods are:
This method returns a list of the methods the server has, by name.
This is an introspection method.
This method returns a description of the argument format a particular method expects. You optionally supply this information when you add the method to the registry. If you don't supply the information, the response is of a form (defined by the introspection standard) that says, "I don't know."
This method returns a text description of a particular method. You supply this information when you add the method to the registry. If you don't this method returns "I know nothing."
This method returns information about the server's capabilities at the XML-RPC level. A client can use this information to tell how to talk to the server. This is information determined entirely by what Xmlrpc-c code is running -- it is hardcoded into Xmlrpc-c.
There are no parameters.
The result is a structure. The members of the structure are as follows:
key | type | value |
---|---|---|
facility | string | This is meant to be the most general class of XML-RPC facility. Its value is xmlrpc-c, and will be in all future releases of Xmlrpc-c. |
version_major | integer | Major version number to qualify facility. The Xmlrpc-c major release number. E.g. for Xmlrpc-c 1.15.02, it is 1. |
version_minor | integer | Same as version_major, except for the minor number. E.g. for Xmlrpc-c 1.15.02, it is 15. |
version_point | integer | Same as version_point, except for the point number. E.g. for Xmlrpc-c 1.15.02, it is 2. |
protocol_version | integer | The version of the protocol spoken by the server. For a true XML-RPC
server, this is meaningless because there is only one XML-RPC. But since
servers often speak extensions of XML-RPC, this number can differentiate.
The number is such that protocol version N is backward compatible with version N-1. I.e. a client can do a simple greater-than test to determine how to talk to the server. Xmlrpc-c returns 2 for this. That alludes to the fact that it speaks an extension to pure and minimal XML-RPC, which would be 1. |
The architectural intent of this method is to have members added in future releases of Xmlrpc-c to refer to newly added features. Clients ideally will never make decisions based on the facility, facility version, and protocol version.
Note that this is an Xmlrpc-c invention. This method does not exist (so far as I know, May 2008) on any server not running Xmlrpc-c. But the architectural intent is that it exist on other servers.
Do not confuse this with system.getCapabilities. The two methods have similar goals; the conceptual differences are:
This method was new in Xmlrpc-c 1.15 (June 2008).
This method returns information about the server's capabilities at the XML-RPC level. A client can use this information to tell how to talk to the server. This is information determined entirely by what Xmlrpc-c code is running -- it is hardcoded into Xmlrpc-c.
This is a standard method found on many XML-RPC servers, whether they run Xmlrpc-c or not.
There are no parameters.
The result is a structure. The members of the structure are as follows:
key | type | value | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
introspection | structure |
As specified by the introspection specification:
|
The architectural intent of this method is to have structure members added in future releases of Xmlrpc-c to refer to newly added standard features. Each will have a characteristic, standard member name.
This method was new in Xmlrpc-c 1.18 (March 2009).
This method tells you whether or not a method by a specified name exists on the server.
The method has one argument: the method name in question, as a string.
The result is a boolean value: true means the method exists; false means it doesn't.
Note that this is not part of the XML-RPC Introspection facility. So it works even on a server on which introspection is disabled.
This method was new in Xmlrpc-c 1.15 (June 2008).
This method shuts down the server.
Since shutting down the server is not really something that can be done internally to the registry, it does all the work by calling the shutdown function that was set in the registry with xmlrpc_registry_set_shutdown to do this. If you did not set the shutdown function (did not call xmlrpc_registry_set_shutdown), system.shutdown fails.
Note that Xmlrpc-c's C Abyss XML-RPC server facilities provide a suitable shutdown function when you set the server up properly. See the enable_shutdown server parameter.
This method has one argument: an explanation of why you are shutting down the server, as a string. Your shutdown function gets this string value and does what it wants with it; a typical use is to record it in a log for use by an administrator.
This method takes an array describing multiple XML-RPC calls, executes them, and returns an array of responses.
This section describes the client-facing interface to the method registry. This is the interface that an XML-RPC protocol driver uses to talk to the registry.
xmlrpc_registry_process_call() executes an XML-RPC call, given in XML form, and returns the response, again in XML form. This entails looking up the named method in the registry and calling the method function associated with it.
Prototype:
void
xmlrpc_registry_process_call2(xmlrpc_env * envP,
xmlrpc_registry * registryP,
char * callXml,
size_t callLen,
void * callInfo,
xmlrpc_mem_block ** outputPP);
envP is an error environment variable pointer. xmlrpc_registry_process_call2() does not return failures of the method via this; if the method fails, xmlrpc_registry_process_call2() still succeeds, and returns an XML-RPC response that indicates the method failure. envP is for internal problems that prevent the method from executing at all.
registryP identifies the method registry through which the call is to be made. You must have previously created this registry and added appropriate methods to it.
callXml and callLen are an ASCII array/length string that contains the complete XML of the XML-RPC call. It isn't necessarily valid.
The function returns at outputPP a memory block with elements of type char. It is the complete XML of the XML-RPC response to the XML-RPC call. You create the memory block. The caller destroys it. The registry ensures that this is a valid XML-RPC response, regardless of what the method function does.
To make this function trace the XML input and output, see the XMLRPC_TRACE_XML environment variable.
This function was new in Xmlrpc-c 1.07 (October 2006). Before that, use xmlrpc_registry_process_call().
xmlrpc_registry_process_call() is the same as xmlrpc_registry_process_call2() with a null callInfo argument. It is obsolete; use xmlrpc_registry_process_call2() instead if possible.
Prototype:
xmlrpc_mem_block *
xmlrpc_registry_process_call(xmlrpc_env * envP,
xmlrpc_registry * registryP,
char * host,
char * callXml,
size_t callLen);
The return value takes the place of the outputPP argument of xmlrpc_registry_process_call2().
host is meaningless. See xmlrpc_registry_add_method2() for an explanation of the history of this argument.
Method registry facilities that execute an RPC may generate a fault response for the RPC. Sometimes the details of that fault are supplied by the registered method function; sometimes they come from Xmlrpc-c directly.
Where Xmlrpc-c generates a fault directly, the fault code is one of the ones enumerated for environment variables. Where Xmlrpc-c takes fault information from the registered method function, the fault code is entirely up to that function. Note that this means Xmlrpc-c does not conform to the Fault Code Interoperability standard.
This function tells you the maximum method function stack space among all the methods registered in the registry. You could use this information to allocate a stack in a thread that is going to execute some method via the registry. E.g. a thread that calls xmlrpc_registry_process_call2().
Prototype:
size_t
xmlrpc_registry_max_stackSize(xmlrpc_registry * const registryP);
The value returned concerns only the method functions themselves, using information provided by whoever registered them (see the stackSize member of the struct xmlrpc_method_info3 argument to xmlrpc_registry_add_method3). A thread that executes methods also has to allow stack space for whatever calls those functions.
Where the user didn't provide stack size information, Xmlrpc-c guesses.
If there are no methods registered, xmlrpc_registry_max_stackSize() returns 0.
This function was new in Xmlrpc-c 1.16 (September 2008). Older Xmlrpc-c provides no facility for managing stack size.
This section describes some facilities and techniques for debugging programs that use libxmlrpc_server.
First of all, if a library call fails, look at the error message! Almost every Xmlrpc-c library call returns a detailed English description of why it failed. See Error Environment Variable.
And you must check each call for failure. If you fail to notice that a library call has failed, you will be quite confused about the results of subsequent calls. Note that example code often doesn't check each call for failure, because it clutters code which is trying to demonstrate something else. So if the example doesn't work for you, insert error checking in the obvious places.
The trace facilities described here write messages to the Standard Error file descriptor via the Standard Error stream of the standard C library (stderr). So make sure you have one. Many server processes don't (they explicitly close the one that the system setup code provides).
If you set the XMLRPC_TRACE_XML environment variable to 1, the libxmlrpc_server registry functions print to Standard Error the XML of the call and of the response, in addition to their normal processing.
Note that this same environment variable does the same thing for Xmlrpc-c clients, in the same way. See client documentation for the gritty details.
Once you've implemented an XML-RPC server (regardless of whether you use Xmlrpc-c libraries to do it), you need a convenient way to send it RPCs and test it out.
Xmlrpc-c's xmlrpc program is good for that. It lets you generate just about any XML-RPC RPC and see the result.
There used to be online XML-RPC client services, where you fill in a form in a web page and either the web server or your browser sends an RPC to an XML-RPC server of your choice. But as of August 2012, the one at gggeek.damacom.it doesn't exist, and likewise gggeek.raprap.it, and the one at phpxmlrpc.sourceforge.io doesn't work (doesn't make a TCP connection to the server, then complains that it didn't get an accectable HTTP response from it).
xmlrpc_server_version() tells you what version (release, level) of libxmlrpc_server is linked to your program.
Example:
unsigned int major, minor, point;
xmlrpc_server_version(&major, &minor, &point);
printf("libxmlrpc_server version %u.%u.%u\n", major, minor, point);
Prototype:
void
xmlrpc_server_version(unsigned int * const majorP,
unsigned int * const minorP,
unsigned int * const pointP);
This is declared in <xmlrpc-c/server.h> as follows:
The numbers returned are those you see in regular text references to the version of XML-RPC For C/++ from which that libxmlrpc_server comes, E.g. "1.16.31."
This function was new in Xmlrpc-c 1.25 (December 2010). Before that, you can use the following external integer variables (Still available, but now deprecated, because it's not possible to export integer variables directly in a Windows DLL).
extern unsigned int const xmlrpc_server_version_major;
extern unsigned int const xmlrpc_server_version_minor;
extern unsigned int const xmlrpc_server_version_point;
These symbols were new in Xmlrpc-c 1.13 (December 2007).