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;
}
예제 #7
0
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);
        }
    }
}
예제 #8
0
 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;
}
예제 #12
0
    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));
        }
    }
예제 #13
0
    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());
    }
}
예제 #16
0
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++);
    }
}