Пример #1
0
void startServer ()
{
    //
    // Execute start up rpc commands.
    //
    if (getConfig ().RPC_STARTUP.isArray ())
    {
        for (int i = 0; i != getConfig ().RPC_STARTUP.size (); ++i)
        {
            const Json::Value& jvCommand    = getConfig ().RPC_STARTUP[i];

            if (!getConfig ().QUIET)
                Log::out() << "Startup RPC: " << jvCommand;

            RPCHandler  rhHandler (&getApp().getOPs ());

            Resource::Charge loadType = Resource::feeReferenceRPC;
            Json::Value jvResult    = rhHandler.doCommand (jvCommand, Config::ADMIN, loadType);

            if (!getConfig ().QUIET)
                Log::out() << "Result: " << jvResult;
        }
    }

    getApp().run ();                 // Blocks till we get a stop RPC.
}
void startServer ()
{
    //
    // Execute start up rpc commands.
    //
    if (getConfig ().RPC_STARTUP.isArray ())
    {
        for (int i = 0; i != getConfig ().RPC_STARTUP.size (); ++i)
        {
            const Json::Value& jvCommand    = getConfig ().RPC_STARTUP[i];

            if (!getConfig ().QUIET)
                Log::out() << "Startup RPC: " << jvCommand;

            RPCHandler  rhHandler (&getApp().getOPs ());

            // VFALCO TODO Clean up this magic number
            LoadType loadType = LT_RPCReference;
            Json::Value jvResult    = rhHandler.doCommand (jvCommand, RPCHandler::ADMIN, &loadType);

            if (!getConfig ().QUIET)
                Log::out() << "Result: " << jvResult;
        }
    }

    getApp().run ();                 // Blocks till we get a stop RPC.
}
Пример #3
0
void startServer ()
{
    //
    // Execute start up rpc commands.
    //
    if (theConfig.RPC_STARTUP.isArray ())
    {
        for (int i = 0; i != theConfig.RPC_STARTUP.size (); ++i)
        {
            const Json::Value& jvCommand    = theConfig.RPC_STARTUP[i];

            if (!theConfig.QUIET)
                std::cerr << "Startup RPC: " << jvCommand << std::endl;

            RPCHandler  rhHandler (&theApp->getOPs ());

            // VFALCO TODO Clean up this magic number
            LoadType loadType = LT_RPCReference;
            Json::Value jvResult    = rhHandler.doCommand (jvCommand, RPCHandler::ADMIN, &loadType);

            if (!theConfig.QUIET)
                std::cerr << "Result: " << jvResult << std::endl;
        }
    }

    theApp->run ();                 // Blocks till we get a stop RPC.
}
Пример #4
0
void RPCHandlerIntermediary::down(MessageContext * context)
throw (IntermediaryException,ResponseException) {


    // Get Qualifier
    //--------------------
    string qualifier = context->getMessage()->getQualifier();

    // No Qualifier -> fail
    //-----------------
    if (qualifier.length()==0) {

        stringstream ss;
        ss << "The input message did not have a qualifier. This is required to find a handler factory";

        Logging::getLogger("wsb.libremote.intermediary.rpchandler")->errorStream() << ss.str();

        throw ss.str();

    }
    // No Matching Factory -> fail
    //-----------------
    else if (this->handlerFactories.count(qualifier)==0) {

        stringstream ss;
        ss << "The input qualifier has no registered Factory. This is required to handle the message";

        Logging::getLogger("wsb.libremote.intermediary.rpchandler")->errorStream() << ss.str();

        throw ss.str();

    }

    // There is a Factory -> Proceed
    //--------------------
    RPCHandlerFactory * factory = this->handlerFactories[qualifier];

    //-- Instanciate handler
    RPCHandler *  handler = factory->newInstance(context);

    Message * response = handler->handle(context);


    // If there is a response -> trigger
    //-----------------
    if (response != NULL) {
        throw ResponseException(response);
    }

}
Пример #5
0
// VFALCO ARGH! returning a single std::string for the entire response?
std::string
ServerHandlerImp::processRequest (std::string const& request,
    beast::IP::Endpoint const& remoteIPAddress)
{
    Json::Value jvRequest;
    {
        Json::Reader reader;
        if ((request.size () > 1000000) ||
            ! reader.parse (request, jvRequest) ||
            jvRequest.isNull () ||
            ! jvRequest.isObject ())
        {
            return createResponse (400, "Unable to parse request");
        }
    }

    auto const role = getConfig ().getAdminRole (jvRequest, remoteIPAddress);

    Resource::Consumer usage;

    if (role == Config::ADMIN)
        usage = m_resourceManager.newAdminEndpoint (remoteIPAddress.to_string());
    else
        usage = m_resourceManager.newInboundEndpoint(remoteIPAddress);

    if (usage.disconnect ())
        return createResponse (503, "Server is overloaded");

    // Parse id now so errors from here on will have the id
    //
    // VFALCO NOTE Except that "id" isn't included in the following errors.
    //
    Json::Value const id = jvRequest ["id"];

    Json::Value const method = jvRequest ["method"];

    if (method.isNull ())
        return createResponse (400, "Null method");

    if (! method.isString ())
        return createResponse (400, "method is not string");

    std::string strMethod = method.asString ();
    if (strMethod.empty())
        return createResponse (400, "method is empty");

    // Parse params
    Json::Value params = jvRequest ["params"];

    if (params.isNull ())
        params = Json::Value (Json::arrayValue);

    else if (!params.isArray ())
        return HTTPReply (400, "params unparseable");

    // VFALCO TODO Shouldn't we handle this earlier?
    //
    if (role == Config::FORBID)
    {
        // VFALCO TODO Needs implementing
        // FIXME Needs implementing
        // XXX This needs rate limiting to prevent brute forcing password.
        return HTTPReply (403, "Forbidden");
    }


    std::string response;
    RPCHandler rpcHandler (m_networkOPs);
    Resource::Charge loadType = Resource::feeReferenceRPC;

    m_journal.debug << "Query: " << strMethod << params;

    Json::Value const result (rpcHandler.doRpcCommand (
        strMethod, params, role, loadType));
    m_journal.debug << "Reply: " << result;

    usage.charge (loadType);

    response = JSONRPCReply (result, Json::Value (), id);

    return createResponse (200, response);
}
Пример #6
0
    // Stolen directly from RPCServerHandler
    std::string processRequest (std::string const& request, std::string const& remoteAddress)
    {
        Json::Value jvRequest;
        {
            Json::Reader reader;

            if (! reader.parse (request, jvRequest) ||
                jvRequest.isNull () ||
                ! jvRequest.isObject ())
            {
                return createResponse (400, "Unable to parse request");
            }
        }

        Config::Role const role (getConfig ().getAdminRole (jvRequest, remoteAddress));

        // Parse id now so errors from here on will have the id
        //
        // VFALCO NOTE Except that "id" isn't included in the following errors...
        //
        Json::Value const id = jvRequest ["id"];

        Json::Value const method = jvRequest ["method"];

        if (method.isNull ())
        {
            return createResponse (400, "Null method");
        }
        else if (! method.isString ())
        {
            return createResponse (400, "method is not string");
        }

        std::string strMethod = method.asString ();

        // Parse params
        Json::Value params = jvRequest ["params"];

        if (params.isNull ())
        {
            params = Json::Value (Json::arrayValue);
        }
        else if (!params.isArray ())
        {
            return HTTPReply (400, "params unparseable");
        }

        // VFALCO TODO Shouldn't we handle this earlier?
        //
        if (role == Config::FORBID)
        {
            // VFALCO TODO Needs implementing
            // FIXME Needs implementing
            // XXX This needs rate limiting to prevent brute forcing password.
            return HTTPReply (403, "Forbidden");
        }

        // This code does all the work on the io_service thread and
        // has no rate-limiting based on source IP or anything.
        // This is a temporary safety
        if ((role != Config::ADMIN) && (getApp().getFeeTrack().isLoadedLocal()))
        {
            return HTTPReply (503, "Unable to service at this time");
        }

        std::string response;

        m_journal.debug << "Query: " << strMethod << params;

        RPCHandler rpcHandler (&m_networkOPs);

        LoadType loadType = LT_RPCReference;

        Json::Value const result (rpcHandler.doRpcCommand (
            strMethod, params, role, &loadType));
        // VFALCO NOTE We discard loadType since there is no endpoint to punish

        m_journal.debug << "Reply: " << result;

        response = JSONRPCReply (result, Json::Value (), id);

        return createResponse (200, response);
    }
Пример #7
0
Json::Value WSConnection::invokeCommand (Json::Value& jvRequest)
{
    if (getConsumer().disconnect ())
    {
        disconnect ();
        return rpcError (rpcSLOW_DOWN);
    }

    // Requests without "command" are invalid.
    //
    if (!jvRequest.isMember (jss::command))
    {
        Json::Value jvResult (Json::objectValue);

        jvResult[jss::type]    = jss::response;
        jvResult[jss::status]  = jss::error;
        jvResult[jss::error]   = jss::missingCommand;
        jvResult[jss::request] = jvRequest;

        if (jvRequest.isMember (jss::id))
        {
            jvResult[jss::id]  = jvRequest[jss::id];
        }

        getConsumer().charge (Resource::feeInvalidRPC);

        return jvResult;
    }

    Resource::Charge loadType = Resource::feeReferenceRPC;
    RPCHandler  mRPCHandler (m_netOPs, std::dynamic_pointer_cast<InfoSub> (this->shared_from_this ()));
    Json::Value jvResult (Json::objectValue);

    Config::Role const role = m_isPublic
            ? Config::GUEST     // Don't check on the public interface.
            : getConfig ().getAdminRole (
                jvRequest, m_remoteAddress);

    if (Config::FORBID == role)
    {
        jvResult[jss::result]  = rpcError (rpcFORBIDDEN);
    }
    else
    {
        jvResult[jss::result] = mRPCHandler.doCommand (jvRequest, role, loadType);
    }

    getConsumer().charge (loadType);
    if (getConsumer().warn ())
    {
        jvResult[jss::warning] = jss::load;
    }

    // Currently we will simply unwrap errors returned by the RPC
    // API, in the future maybe we can make the responses
    // consistent.
    //
    // Regularize result. This is duplicate code.
    if (jvResult[jss::result].isMember (jss::error))
    {
        jvResult               = jvResult[jss::result];
        jvResult[jss::status]  = jss::error;
        jvResult[jss::request] = jvRequest;

    }
    else
    {
        jvResult[jss::status]  = jss::success;
    }

    if (jvRequest.isMember (jss::id))
    {
        jvResult[jss::id]      = jvRequest[jss::id];
    }

    jvResult[jss::type]        = jss::response;

    return jvResult;
}
// ==========================================================================
// METHOD RPCRequestHandler::run
// ==========================================================================
int RPCRequestHandler::run (string &uri, string &postbody, value &inhdr,
                 		    string &out, value &outhdr, value &env,
                		    tcpsocket &s)
{
	try
	{
		DEBUG.storeFile ("RPCRequestHandler","postbody", postbody, "run");
		CORE->log (log::debug, "RPC", "handle: %S %!" %format (uri, inhdr));
		value indata;
		value res;
		string origin = "rpc";
		uid_t uid = 0;
		RPCHandler hdl (sdb);
	
		indata.fromjson (postbody);
		if (inhdr.exists ("X-OpenCORE-Origin"))
		{
			origin = inhdr["X-OpenCORE-Origin"];
		}
		
		CORE->log (log::debug, "RPC", "body: %!" %format (indata));
		
		// Set up credentials if available
		s.getcredentials();
		CORE->log (log::debug, "RPC", "credentials: %d %d %d", s.peer_uid,
														s.peer_gid, s.peer_pid);
		if (s.peer_pid == 0)
		{
			string peer_name = s.peer_name;
			if (peer_name == "127.0.0.1")
			{
				if (inhdr.exists ("X-Forwarded-For"))
				{
					peer_name = inhdr["X-Forwarded-For"];
				}
			}
				
			if (origin.strchr ('/') >0) origin = origin.cutat ('/');
			if (! origin) origin = "RPC";

			origin.strcat ("/src=%s" %format (peer_name));
			env["ip"] = s.peer_name = peer_name;
		}

		if (indata.exists ("header") && indata["header"].exists ("command"))
		{
			uri.strcat ("/%s" %format (indata["header"]["command"]));
		}
	
		res = hdl.handle (indata, s.peer_uid, origin);	
		out = res.tojson ();
		
		if (inhdr.exists ("Accept-Encoding"))
		{
			string ae = inhdr["Accept-Encoding"];
			if (ae.strstr ("deflate") >= 0)
			{
				unsigned long reslen = (out.strlen() * 1.05) + 12;
				char buf[reslen];
				
				if (compress2 ((Bytef*) buf, &reslen,
							   (const Bytef*) out.str(), out.strlen(), 4) == Z_OK)
				{
					outhdr["Content-Encoding"] = "deflate";
					out.strcpy (buf+2, reslen-2);
				}
				else
				{
					log::write (log::warning, "RPC", "Compress error");
				}
			}
		}
		
		outhdr["Content-type"] = "application/json";
	}
	catch (...)
	{
		log::write (log::error, "RPC", "Exception caught");
	}
	return HTTP_OK;
}