mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-07-06 20:31:50 +00:00
290 lines
7.1 KiB
C
290 lines
7.1 KiB
C
/* Transport some XML to a server and get the response back, as if doing
|
|
an XML-RPC call.
|
|
*/
|
|
|
|
#define _XOPEN_SOURCE 600 /* Make sure strdup() is in <string.h> */
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "xmlrpc_config.h" /* information about this build environment */
|
|
#include "casprintf.h"
|
|
#include "mallocvar.h"
|
|
#include "cmdline_parser.h"
|
|
|
|
#include "xmlrpc-c/base.h"
|
|
#include "xmlrpc-c/client.h"
|
|
|
|
#define NAME "xmlrpc_transport command line program"
|
|
#define VERSION "1.0"
|
|
|
|
struct cmdlineInfo {
|
|
const char * url;
|
|
const char * username;
|
|
const char * password;
|
|
const char * transport;
|
|
/* Name of XML transport he wants to use. NULL if he has no
|
|
preference.
|
|
*/
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
die_if_fault_occurred (xmlrpc_env * const envP) {
|
|
if (envP->fault_occurred) {
|
|
fprintf(stderr, "Error: %s (%d)\n",
|
|
envP->fault_string, envP->fault_code);
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void GNU_PRINTF_ATTR(2,3)
|
|
setError(xmlrpc_env * const envP, const char format[], ...) {
|
|
va_list args;
|
|
const char * faultString;
|
|
|
|
va_start(args, format);
|
|
|
|
cvasprintf(&faultString, format, args);
|
|
va_end(args);
|
|
|
|
xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR, faultString);
|
|
|
|
strfree(faultString);
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
processArguments(xmlrpc_env * const envP,
|
|
cmdlineParser const cp,
|
|
struct cmdlineInfo * const cmdlineP) {
|
|
|
|
if (cmd_argumentCount(cp) < 1)
|
|
setError(envP, "Not enough arguments. Need a URL.");
|
|
else {
|
|
cmdlineP->url = cmd_getArgument(cp, 0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
parseCommandLine(xmlrpc_env * const envP,
|
|
int const argc,
|
|
const char ** const argv,
|
|
struct cmdlineInfo * const cmdlineP) {
|
|
|
|
cmdlineParser const cp = cmd_createOptionParser();
|
|
|
|
const char * error;
|
|
|
|
cmd_defineOption(cp, "transport", OPTTYPE_STRING);
|
|
cmd_defineOption(cp, "username", OPTTYPE_STRING);
|
|
cmd_defineOption(cp, "password", OPTTYPE_STRING);
|
|
|
|
cmd_processOptions(cp, argc, argv, &error);
|
|
|
|
if (error) {
|
|
setError(envP, "Command syntax error. %s", error);
|
|
strfree(error);
|
|
} else {
|
|
cmdlineP->username = cmd_getOptionValueString(cp, "username");
|
|
cmdlineP->password = cmd_getOptionValueString(cp, "password");
|
|
|
|
if (cmdlineP->username && !cmdlineP->password)
|
|
setError(envP, "When you specify -username, you must also "
|
|
"specify -password.");
|
|
else {
|
|
cmdlineP->transport = cmd_getOptionValueString(cp, "transport");
|
|
|
|
processArguments(envP, cp, cmdlineP);
|
|
}
|
|
}
|
|
cmd_destroyOptionParser(cp);
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
freeCmdline(struct cmdlineInfo const cmdline) {
|
|
|
|
strfree(cmdline.url);
|
|
if (cmdline.username)
|
|
strfree(cmdline.username);
|
|
if (cmdline.password)
|
|
strfree(cmdline.password);
|
|
if (cmdline.transport)
|
|
strfree(cmdline.transport);
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
computeUrl(const char * const urlArg,
|
|
const char ** const urlP) {
|
|
|
|
if (strstr(urlArg, "://") != 0) {
|
|
*urlP = strdup(urlArg);
|
|
} else {
|
|
casprintf(urlP, "http://%s/RPC2", urlArg);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
doCall(xmlrpc_env * const envP,
|
|
const char * const transport,
|
|
const xmlrpc_server_info * const serverInfoP,
|
|
xmlrpc_mem_block * const callXmlP,
|
|
xmlrpc_mem_block ** const respXmlPP) {
|
|
|
|
struct xmlrpc_clientparms clientparms;
|
|
|
|
clientparms.transport = transport;
|
|
|
|
clientparms.transportparmsP = NULL;
|
|
clientparms.transportparm_size = 0;
|
|
|
|
xmlrpc_client_init2(envP, XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION,
|
|
&clientparms, XMLRPC_CPSIZE(transportparm_size));
|
|
if (!envP->fault_occurred) {
|
|
xmlrpc_client_transport_call(envP, NULL, serverInfoP,
|
|
callXmlP, respXmlPP);
|
|
|
|
xmlrpc_client_cleanup();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
createServerInfo(xmlrpc_env * const envP,
|
|
const char * const serverUrl,
|
|
const char * const userName,
|
|
const char * const password,
|
|
xmlrpc_server_info ** const serverInfoPP) {
|
|
|
|
xmlrpc_server_info * serverInfoP;
|
|
|
|
serverInfoP = xmlrpc_server_info_new(envP, serverUrl);
|
|
if (!envP->fault_occurred) {
|
|
if (userName) {
|
|
xmlrpc_server_info_set_basic_auth(
|
|
envP, serverInfoP, userName, password);
|
|
}
|
|
}
|
|
*serverInfoPP = serverInfoP;
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
readFile(xmlrpc_env * const envP,
|
|
FILE * const ifP,
|
|
xmlrpc_mem_block ** const fileContentsPP) {
|
|
|
|
xmlrpc_mem_block * fileContentsP;
|
|
|
|
fileContentsP = XMLRPC_MEMBLOCK_NEW(char, envP, 0);
|
|
|
|
while (!envP->fault_occurred && !feof(ifP)) {
|
|
char buffer[4096];
|
|
size_t bytesRead;
|
|
|
|
bytesRead = fread(buffer, 1, sizeof(buffer), ifP);
|
|
XMLRPC_MEMBLOCK_APPEND(char, envP,
|
|
fileContentsP, buffer, bytesRead);
|
|
}
|
|
if (envP->fault_occurred)
|
|
XMLRPC_MEMBLOCK_FREE(char, fileContentsP);
|
|
|
|
*fileContentsPP = fileContentsP;
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
writeFile(xmlrpc_env * const envP,
|
|
FILE * const ofP,
|
|
xmlrpc_mem_block * const fileContentsP) {
|
|
|
|
size_t totalWritten;
|
|
|
|
totalWritten = 0;
|
|
|
|
while (!envP->fault_occurred &&
|
|
totalWritten < XMLRPC_MEMBLOCK_SIZE(char, fileContentsP)) {
|
|
size_t bytesWritten;
|
|
|
|
bytesWritten = fwrite(
|
|
XMLRPC_MEMBLOCK_CONTENTS(char, fileContentsP) + totalWritten,
|
|
1,
|
|
XMLRPC_MEMBLOCK_SIZE(char, fileContentsP) - totalWritten,
|
|
ofP);
|
|
|
|
if (bytesWritten < 1)
|
|
xmlrpc_env_set_fault_formatted(
|
|
envP, XMLRPC_INTERNAL_ERROR,
|
|
"Error writing output");
|
|
|
|
totalWritten -= bytesWritten;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int
|
|
main(int const argc,
|
|
const char ** const argv) {
|
|
|
|
struct cmdlineInfo cmdline;
|
|
xmlrpc_env env;
|
|
xmlrpc_mem_block * callXmlP;
|
|
xmlrpc_mem_block * respXmlP;
|
|
const char * url;
|
|
xmlrpc_server_info * serverInfoP;
|
|
|
|
xmlrpc_env_init(&env);
|
|
|
|
parseCommandLine(&env, argc, argv, &cmdline);
|
|
die_if_fault_occurred(&env);
|
|
|
|
computeUrl(cmdline.url, &url);
|
|
|
|
createServerInfo(&env, url, cmdline.username, cmdline.password,
|
|
&serverInfoP);
|
|
die_if_fault_occurred(&env);
|
|
|
|
fprintf(stderr, "Reading call data from Standard Input...\n");
|
|
|
|
readFile(&env, stdin, &callXmlP);
|
|
die_if_fault_occurred(&env);
|
|
|
|
fprintf(stderr, "Making call...\n");
|
|
|
|
doCall(&env, cmdline.transport, serverInfoP, callXmlP,
|
|
&respXmlP);
|
|
die_if_fault_occurred(&env);
|
|
|
|
fprintf(stderr, "Writing response data to Standard Output\n");
|
|
writeFile(&env, stdout, respXmlP);
|
|
die_if_fault_occurred(&env);
|
|
|
|
XMLRPC_MEMBLOCK_FREE(char, callXmlP);
|
|
XMLRPC_MEMBLOCK_FREE(char, respXmlP);
|
|
|
|
strfree(url);
|
|
|
|
freeCmdline(cmdline);
|
|
|
|
xmlrpc_env_clean(&env);
|
|
|
|
return 0;
|
|
}
|