static value i8ValFromParm(string const& valueString) { value retval; if (valueString.length() < 1) throwf("Integer argument has nothing after the 'I/'"); else { long long value; char * tailptr; errno = 0; value = strtoll(valueString.c_str(), &tailptr, 10); if (errno == ERANGE) throwf("'%s' is out of range for a 64 bit integer", valueString.c_str()); else if (errno != 0) throwf("Mysterious failure of strtoll(), errno=%d (%s)", errno, strerror(errno)); else { if (*tailptr != '\0') throwf("64 bit integer argument has non-digit crap " "in it: '%s'", tailptr); else retval = value_i8(value); } } return retval; }
static value bytestringValFromParm(string const& valueString) { value retval; if (valueString.length() / 2 * 2 != valueString.length()) throwf("Hexadecimal text is not an even " "number of characters (it is %u characters)", valueString.length()); else { vector<unsigned char> byteString(valueString.length() / 2); size_t strCursor; strCursor = 0; while (strCursor < valueString.length()) { string const hexByte(valueString.substr(strCursor, 2)); unsigned char byte; int rc; rc = sscanf(hexByte.c_str(), "%2hhx", &byte); byteString.push_back(byte); if (rc != 1) throwf("Invalid hex data '%s'", hexByte.c_str()); else strCursor += 2; } retval = value_bytestring(byteString); } return retval; }
static void parseCommandLine(cmdlineInfo * const cmdlineP, int const argc, const char ** const argv) { CmdlineParser cp; cp.defineOption("serverfd", CmdlineParser::UINT); try { cp.processOptions(argc, argv); } catch (exception const& e) { throwf("Command syntax error. %s", e.what()); } if (cp.optionIsPresent("serverfd")) { cmdlineP->serverfd = cp.getOptionValueUint("serverfd"); } else cmdlineP->serverfd = 3; if (cp.argumentCount() < 1) cmdlineP->interactive = true; else { cmdlineP->interactive = false; cmdlineP->methodName = cp.getArgument(0); for (uint argI = 1; argI < cp.argumentCount(); ++argI) cmdlineP->params.push_back(cp.getArgument(argI)); } }
int main(int const argc, const char ** const argv) { try { cmdlineInfo cmdline(argc, argv); signal(SIGPIPE, SIG_IGN); clientXmlTransport_pstream myTransport( clientXmlTransport_pstream::constrOpt() .fd(cmdline.serverfd)); client_xml myClient(&myTransport); if (cmdline.interactive) { if (cmdline.serverfd == STDIN_FILENO || cmdline.serverfd == STDOUT_FILENO) throwf("Can't use Stdin or Stdout for the server fd when " "running interactively."); doInteractive(&myClient); } else doCommand(&myClient, cmdline.methodName, cmdline.params); } catch (exception const& e) { cerr << "Failed. " << e.what() << endl; } catch (...) { cerr << "Code threw unrecognized exception" << endl; abort(); } return 0; }
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. -----------------------------------------------------------------------------*/ defaultMethod * const methodP = static_cast<defaultMethod *>(methodPtr); paramList const paramList(pListFromXmlrpcArray(paramArrayP)); xmlrpc_value * retval; retval = NULL; // silence used-before-set warning try { xmlrpc_c::value result; try { methodP->execute(methodName, paramList, &result); } catch (xmlrpc_c::fault const& fault) { xmlrpc_env_set_fault(envP, fault.getCode(), fault.getDescription().c_str()); } if (!envP->fault_occurred) { if (result.isInstantiated()) retval = result.cValue(); else throwf("Xmlrpc-c user's xmlrpc_c::defaultMethod object's " "'execute method' failed to set the RPC result " "value."); } } catch (exception const& e) { xmlrpc_faultf(envP, "Unexpected error executing default " "method code, detected by Xmlrpc-c " "method registry code. Method did not " "fail; rather, it did not complete at all. %s", e.what()); } catch (...) { xmlrpc_env_set_fault(envP, XMLRPC_INTERNAL_ERROR, "Unexpected error executing default " "method code, detected by Xmlrpc-c " "method registry code. Method did not " "fail; rather, it did not complete at all."); } return retval; }
static value parameterFromArg(string const& paramArg) { value param; try { if (paramArg.substr(0, 2) == "s/") param = value_string(paramArg.substr(2)); else if (paramArg.substr(0, 2) == "h/") param = bytestringValFromParm(paramArg.substr(2)); else if (paramArg.substr(0, 2) == "i/") param = intValFromParm(paramArg.substr(2)); else if (paramArg.substr(0, 2) == "I/") param = i8ValFromParm(paramArg.substr(2)); else if (paramArg.substr(0, 2) == "d/") param = doubleValFromParm(paramArg.substr(2)); else if (paramArg.substr(0, 2) == "b/") param = boolValFromParm(paramArg.substr(2)); else if (paramArg.substr(0, 2) == "n/") param = nilValFromParm(paramArg.substr(2)); else { /* It's not in normal type/value format, so we take it to be the shortcut string notation */ param = value_string(paramArg); } } catch (exception const& e) { throwf("Failed to interpret parameter argument '%s'. %s", paramArg.c_str(), e.what()); } return param; }
void parseResponse(string const& responseXml, rpcOutcome * const outcomeP) { /*---------------------------------------------------------------------------- Parse the XML for an XML-RPC response into an XML-RPC result value. -----------------------------------------------------------------------------*/ env_wrap env; xmlrpc_value * c_resultP; int faultCode; const char * faultString; xmlrpc_parse_response2(&env.env_c, responseXml.c_str(), responseXml.size(), &c_resultP, &faultCode, &faultString); if (env.env_c.fault_occurred) throwf("Unable to find XML-RPC response in what server sent back. %s", env.env_c.fault_string); else { if (faultString) { *outcomeP = rpcOutcome(fault(faultString, static_cast<fault::code_t>(faultCode))); xmlrpc_strfree(faultString); } else { XMLRPC_ASSERT_VALUE_OK(c_resultP); *outcomeP = rpcOutcome(value(c_resultP)); xmlrpc_DECREF(c_resultP); } } }
abyssGlobalState() { const char *error; AbyssInit(&error); if (error) { string const e(error); xmlrpc_strfree(error); throwf("AbyssInit() failed. %s", e.c_str()); } }
cmdlineInfo:: cmdlineInfo(int const argc, const char ** const argv) { try { parseCommandLine(this, argc, argv); } catch (exception const& e) { throwf("Command syntax error. %s", e.what()); } }
static value nilValFromParm(string const& valueString) { value retval; if (valueString.length() > 0) throwf("Nil argument has something after the 'n/'"); else retval = value_nil(); return retval; }
static value doubleValFromParm(string const& valueString) { value retval; if (valueString.length() < 1) throwf("\"Double\" argument has nothing after the 'd/'"); else { double value; char * tailptr; value = strtod(valueString.c_str(), &tailptr); if (*tailptr != '\0') throwf("\"Double\" argument has non-decimal crap in it: '%s'", tailptr); else retval = value_double(value); } return retval; }
boundSocket(short const portNumber) { this->fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (this->fd < 0) throwf("socket() failed. errno=%d (%s)", errno, strerror(errno)); struct sockaddr_in sockAddr; int rc; sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons(portNumber); sockAddr.sin_addr.s_addr = 0; rc = bind(this->fd, (struct sockaddr *)&sockAddr, sizeof(sockAddr)); if (rc != 0) { close(this->fd); throwf("Couldn't bind. bind() failed with errno=%d (%s)", errno, strerror(errno)); } }
void call(xmlrpc_c::carriageParm * const carriageParmP, string const& callXml, string * const responseXmlP) { carriageParm_direct * const parmP = dynamic_cast<carriageParm_direct *>(carriageParmP); if (parmP == NULL) throw(error("Carriage parameter passed to the direct " "transport is not type carriageParm_direct")); parmP->registryP->processCall(callXml, responseXmlP); }
static value boolValFromParm(string const& valueString) { value retval; if (valueString == "t" || valueString == "true") retval = value_boolean(true); else if (valueString == "f" || valueString == "false") retval = value_boolean(false); else throwf("Boolean argument has unrecognized value '%s'. " "recognized values are 't', 'f', 'true', and 'false'.", valueString.c_str()); return retval; }
static void doCommand(client_xml * const clientP, string const& methodName, vector<string> const& paramArgs) { value result; callWithClient(clientP, methodName, paramListFromParamArgs(paramArgs), &result); try { dumpResult(result); } catch(exception const& e) { throwf("Error showing result after RPC completed normally. %s", e.what()); } }
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()) throwf("RPC response indicates it failed. %s", outcome.getFault().getDescription().c_str()); *resultP = outcome.getResult(); }
static void callWithClient(client * const clientP, string const& methodName, paramList const& paramList, value * const resultP) { rpcPtr myRpcP(methodName, paramList); carriageParm_pstream myCarriageParm; // Empty - no parm needed try { myRpcP->call(clientP, &myCarriageParm); } catch (exception const& e) { throwf("RPC failed. %s", e.what()); } *resultP = myRpcP->getResult(); }
static void parseCommand(string const& cmd, string * const methodNameP, vector<string> * const paramListP) { list<string> const wordList(parseWordList(cmd)); list<string>::const_iterator cmdWordP; cmdWordP = wordList.begin(); if (cmdWordP == wordList.end()) throwf("Command '%s' does not have a method name", cmd.c_str()); else { *methodNameP = *cmdWordP++; *paramListP = vector<string>(); // Start empty while (cmdWordP != wordList.end()) paramListP->push_back(*cmdWordP++); } }