Ejemplo n.º 1
0
json::value dointernal (rpc::context& context)
{
    // used for debug or special-purpose rpc commands
    if (!context.params.ismember ("internal_command"))
        return rpcerror (rpcinvalid_params);

    auto name = context.params["internal_command"].asstring ();
    auto params = context.params["params"];

    for (auto* h = rpc::internalhandler::headhandler; h; )
    {
        if (name == h->name_)
        {
            writelog (lswarning, rpchandler)
                << "internal command " << name << ": " << params;
            json::value ret = h->handler_ (params);
            writelog (lswarning, rpchandler)
                << "internal command returns: " << ret;
            return ret;
        }

        h = h->nexthandler_;
    }

    return rpcerror (rpcbad_syntax);
}
Ejemplo n.º 2
0
Archivo: trascan.c Proyecto: bazil/tra
void
threadmain(int argc, char **argv)
{
	int i;
	Path *p;

	fmtinstall('H', encodefmt);
	fmtinstall('P', pathfmt);
	fmtinstall('R', rpcfmt);
	fmtinstall('$', statfmt);
	fmtinstall('V', vtimefmt);

	ARGBEGIN{
	case 'D':
		debug |= dbglevel(EARGF(usage()));
		break;
	case 'V':
		traversion();
	default:
		usage();
	}ARGEND

	if(argc < 1)
		usage();

	startclient();
	repl = dialreplica(argv[0]);

	argc--;
	argv++;
	fprint(2, "scan...");
	if(argc == 0){
		fprint(2, "%P...", nil);
		if(rpcstat(repl, nil) == nil)
			sysfatal("rpcstat: %s", rpcerror());
	}else{
		for(i=0; i<argc; i++){
			p = strtopath(argv[i]);
			fprint(2, "%P...", p);
			if(rpcstat(repl, p) == nil)
				sysfatal("rpcstat: %s", rpcerror());
		}
	}
	fprint(2, "hangup...");
	rpchangup(repl);
	fprint(2, "close...");
	replclose(repl);
	fprint(2, "exit\n");
	threadexitsall(nil);
}
Ejemplo n.º 3
0
Archivo: synckids.c Proyecto: bazil/tra
static void
kidthread(void *a)
{
	void *p;
	Kids *k;

	k = a;
	threadsetname("kidthread");
	startclient();
	k->nk = rpckids(k->repl, k->p, &k->k);
	if(k->nk < 0)
		k->err = rpcerror();
	endclient();
	threadstate("kidthread end");
	p = k->c;
	send(k->c, k);
	threadstate("DONE %p", p);
}
Ejemplo n.º 4
0
// {
//   secret: <string>
// }
json::value dovalidationseed (rpc::context& context)
{
    auto lock = getapp().masterlock();
    json::value obj (json::objectvalue);

    if (!context.params.ismember ("secret"))
    {
        std::cerr << "unset validation seed." << std::endl;

        getconfig ().validation_seed.clear ();
        getconfig ().validation_pub.clear ();
        getconfig ().validation_priv.clear ();
    }
    else if (!getconfig ().validation_seed.setseedgeneric (
                 context.params["secret"].asstring ()))
    {
        getconfig ().validation_pub.clear ();
        getconfig ().validation_priv.clear ();

        return rpcerror (rpcbad_seed);
    }
    else
    {
        auto& seed = getconfig ().validation_seed;
        auto& pub = getconfig ().validation_pub;

        pub = rippleaddress::createnodepublic (seed);
        getconfig ().validation_priv = rippleaddress::createnodeprivate (seed);

        obj["validation_public_key"] = pub.humannodepublic ();
        obj["validation_seed"] = seed.humanseed ();
        obj["validation_key"] = seed.humanseed1751 ();
    }

    return obj;
}
Ejemplo n.º 5
0
// {
//   account: <account>|<account_public_key>
//   account_index: <number>        // optional, defaults to 0.
//   ledger_hash : <ledger>
//   ledger_index : <ledger_index>
//   limit: integer                 // optional
//   marker: opaque                 // optional, resume previous query
// }
json::value doaccountlines (rpc::context& context)
{
    auto const& params (context.params);
    if (! params.ismember (jss::account))
        return rpc::missing_field_error ("account");

    ledger::pointer ledger;
    json::value result (rpc::lookupledger (params, ledger, context.netops));
    if (! ledger)
        return result;

    std::string strident (params[jss::account].asstring ());
    bool bindex (params.ismember (jss::account_index));
    int iindex (bindex ? params[jss::account_index].asuint () : 0);
    rippleaddress rippleaddress;

    json::value const jv (rpc::accountfromstring (ledger, rippleaddress, bindex,
        strident, iindex, false, context.netops));
    if (! jv.empty ())
    {
        for (json::value::const_iterator it (jv.begin ()); it != jv.end (); ++it)
            result[it.membername ()] = it.key ();

        return result;
    }

    if (! ledger->hasaccount (rippleaddress))
        return rpcerror (rpcact_not_found);

    std::string strpeer (params.ismember (jss::peer)
        ? params[jss::peer].asstring () : "");
    bool bpeerindex (params.ismember (jss::peer_index));
    int ipeerindex (bindex ? params[jss::peer_index].asuint () : 0);

    rippleaddress rippleaddresspeer;

    if (! strpeer.empty ())
    {
        result[jss::peer] = rippleaddress.humanaccountid ();

        if (bpeerindex)
            result[jss::peer_index] = ipeerindex;

        result = rpc::accountfromstring (ledger, rippleaddresspeer, bpeerindex,
            strpeer, ipeerindex, false, context.netops);

        if (! result.empty ())
            return result;
    }

    account rapeeraccount;
    if (rippleaddresspeer.isvalid ())
        rapeeraccount = rippleaddresspeer.getaccountid ();

    unsigned int limit;
    if (params.ismember (jss::limit))
    {
        auto const& jvlimit (params[jss::limit]);
        if (! jvlimit.isintegral ())
            return rpc::expected_field_error ("limit", "unsigned integer");

        limit = jvlimit.isuint () ? jvlimit.asuint () :
            std::max (0, jvlimit.asint ());

        if (context.role != role::admin)
        {
            limit = std::max (rpc::tuning::minlinesperrequest,
                std::min (limit, rpc::tuning::maxlinesperrequest));
        }
    }
    else
    {
        limit = rpc::tuning::defaultlinesperrequest;
    }

    json::value& jsonlines (result[jss::lines] = json::arrayvalue);
    account const& raaccount(rippleaddress.getaccountid ());
    visitdata visitdata = { {}, raaccount, rippleaddresspeer, rapeeraccount };
    unsigned int reserve (limit);
    uint256 startafter;
    std::uint64_t starthint;

    if (params.ismember (jss::marker))
    {
        // we have a start point. use limit - 1 from the result and use the
        // very last one for the resume.
        json::value const& marker (params[jss::marker]);

        if (! marker.isstring ())
            return rpc::expected_field_error ("marker", "string");

        startafter.sethex (marker.asstring ());
        sle::pointer sleline (ledger->getslei (startafter));

        if (sleline == nullptr || sleline->gettype () != ltripple_state)
            return rpcerror (rpcinvalid_params);

        if (sleline->getfieldamount (sflowlimit).getissuer () == raaccount)
            starthint = sleline->getfieldu64 (sflownode);
        else if (sleline->getfieldamount (sfhighlimit).getissuer () == raaccount)
            starthint = sleline->getfieldu64 (sfhighnode);
        else
            return rpcerror (rpcinvalid_params);

        // caller provided the first line (startafter), add it as first result
        auto const line (ripplestate::makeitem (raaccount, sleline));
        if (line == nullptr)
            return rpcerror (rpcinvalid_params);

        addline (jsonlines, *line, ledger);
        visitdata.items.reserve (reserve);
    }
    else
    {
        starthint = 0;
        // we have no start point, limit should be one higher than requested.
        visitdata.items.reserve (++reserve);
    }

    if (! ledger->visitaccountitems (raaccount, startafter, starthint, reserve,
        [&visitdata](sle::ref slecur)
        {
            auto const line (ripplestate::makeitem (visitdata.accountid, slecur));
            if (line != nullptr &&
                (! visitdata.rippleaddresspeer.isvalid () ||
                visitdata.rapeeraccount == line->getaccountidpeer ()))
            {
                visitdata.items.emplace_back (line);
                return true;
            }

            return false;
        }))
    {
        return rpcerror (rpcinvalid_params);
    }

    if (visitdata.items.size () == reserve)
    {
        result[jss::limit] = limit;

        ripplestate::pointer line (visitdata.items.back ());
        result[jss::marker] = to_string (line->peeksle ().getindex ());
        visitdata.items.pop_back ();
    }

    result[jss::account] = rippleaddress.humanaccountid ();

    for (auto const& item : visitdata.items)
        addline (jsonlines, *item.get (), ledger);

    context.loadtype = resource::feemediumburdenrpc;
    return result;
}
Ejemplo n.º 6
0
// {
//   account: account,
//   ledger_index_min: ledger_index,
//   ledger_index_max: ledger_index,
//   binary: boolean,              // optional, defaults to false
//   count: boolean,               // optional, defaults to false
//   descending: boolean,          // optional, defaults to false
//   offset: integer,              // optional, defaults to 0
//   limit: integer                // optional
// }
json::value doaccounttxold (rpc::context& context)
{
    rippleaddress   raaccount;
    std::uint32_t offset
            = context.params.ismember ("offset")
            ? context.params["offset"].asuint () : 0;
    int limit = context.params.ismember ("limit")
            ? context.params["limit"].asuint () : -1;
    bool bbinary = context.params.ismember ("binary")
            && context.params["binary"].asbool ();
    bool bdescending = context.params.ismember ("descending")
            && context.params["descending"].asbool ();
    bool bcount = context.params.ismember ("count")
            && context.params["count"].asbool ();
    std::uint32_t   uledgermin;
    std::uint32_t   uledgermax;
    std::uint32_t   uvalidatedmin;
    std::uint32_t   uvalidatedmax;
    bool bvalidated  = context.netops.getvalidatedrange (
        uvalidatedmin, uvalidatedmax);

    if (!context.params.ismember ("account"))
        return rpcerror (rpcinvalid_params);

    if (!raaccount.setaccountid (context.params["account"].asstring ()))
        return rpcerror (rpcact_malformed);

    if (offset > 3000)
        return rpcerror (rpcatx_deprecated);

    context.loadtype = resource::feehighburdenrpc;

    // deprecated
    if (context.params.ismember ("ledger_min"))
    {
        context.params["ledger_index_min"]   = context.params["ledger_min"];
        bdescending = true;
    }

    // deprecated
    if (context.params.ismember ("ledger_max"))
    {
        context.params["ledger_index_max"]   = context.params["ledger_max"];
        bdescending = true;
    }

    if (context.params.ismember ("ledger_index_min")
        || context.params.ismember ("ledger_index_max"))
    {
        std::int64_t iledgermin  = context.params.ismember ("ledger_index_min")
                ? context.params["ledger_index_min"].asint () : -1;
        std::int64_t iledgermax  = context.params.ismember ("ledger_index_max")
                ? context.params["ledger_index_max"].asint () : -1;

        if (!bvalidated && (iledgermin == -1 || iledgermax == -1))
        {
            // don't have a validated ledger range.
            return rpcerror (rpclgr_idxs_invalid);
        }

        uledgermin  = iledgermin == -1 ? uvalidatedmin : iledgermin;
        uledgermax  = iledgermax == -1 ? uvalidatedmax : iledgermax;

        if (uledgermax < uledgermin)
        {
            return rpcerror (rpclgr_idxs_invalid);
        }
    }
    else
    {
        ledger::pointer l;
        json::value ret = rpc::lookupledger (context.params, l, context.netops);

        if (!l)
            return ret;

        uledgermin = uledgermax = l->getledgerseq ();
    }

    int count = 0;

#ifndef beast_debug

    try
    {
#endif

        json::value ret (json::objectvalue);

        ret["account"] = raaccount.humanaccountid ();
        json::value& jvtxns = (ret["transactions"] = json::arrayvalue);

        if (bbinary)
        {
            auto txns = context.netops.getaccounttxsb (
                raaccount, uledgermin, uledgermax, bdescending, offset, limit,
                context.role == role::admin);

            for (auto it = txns.begin (), end = txns.end (); it != end; ++it)
            {
                ++count;
                json::value& jvobj = jvtxns.append (json::objectvalue);

                std::uint32_t  uledgerindex = std::get<2> (*it);
                jvobj["tx_blob"]            = std::get<0> (*it);
                jvobj["meta"]               = std::get<1> (*it);
                jvobj["ledger_index"]       = uledgerindex;
                jvobj["validated"]
                        = bvalidated
                        && uvalidatedmin <= uledgerindex
                        && uvalidatedmax >= uledgerindex;

            }
        }
        else
        {
            auto txns = context.netops.getaccounttxs (
                raaccount, uledgermin, uledgermax, bdescending, offset, limit,
                context.role == role::admin);

            for (auto it = txns.begin (), end = txns.end (); it != end; ++it)
            {
                ++count;
                json::value&    jvobj = jvtxns.append (json::objectvalue);

                if (it->first)
                    jvobj["tx"]             = it->first->getjson (1);

                if (it->second)
                {
                    std::uint32_t uledgerindex = it->second->getlgrseq ();

                    jvobj["meta"]           = it->second->getjson (0);
                    jvobj["validated"]
                            = bvalidated
                            && uvalidatedmin <= uledgerindex
                            && uvalidatedmax >= uledgerindex;
                }

            }
        }

        //add information about the original query
        ret["ledger_index_min"] = uledgermin;
        ret["ledger_index_max"] = uledgermax;
        ret["validated"]
                = bvalidated
                && uvalidatedmin <= uledgermin
                && uvalidatedmax >= uledgermax;
        ret["offset"]           = offset;

        // we no longer return the full count but only the count of returned
        // transactions. computing this count was two expensive and this api is
        // deprecated anyway.
        if (bcount)
            ret["count"]        = count;

        if (context.params.ismember ("limit"))
            ret["limit"]        = limit;


        return ret;
#ifndef beast_debug
    }
    catch (...)
    {
        return rpcerror (rpcinternal);
    }

#endif
}
Ejemplo n.º 7
0
// {
//   account: [<account>|<account_public_key>]
//   peer: [<account>|<account_public_key>]
//   currency: <currency>
//   ledger_hash : <ledger>
//   ledger_index : <ledger_index>
// }
json::value doaccountasset (rpc::context& context)
{
    auto const& params(context.params);
    if (!params.ismember(jss::account))
        return rpc::missing_field_error("account");
    if (!params.ismember(jss::peer))
        return rpc::missing_field_error("peer");
    if (!params.ismember(jss::currency))
        return rpc::missing_field_error("currency");

    ledger::pointer ledger;
    json::value result(rpc::lookupledger(params, ledger, context.netops));
    if (!ledger)
        return result;

    std::string strident(params[jss::account].asstring());
    bool bindex(params.ismember(jss::account_index));
    int iindex(bindex ? params[jss::account_index].asuint() : 0);
    rippleaddress rippleaddress;

    json::value const jv(rpc::accountfromstring(ledger, rippleaddress, bindex,
                                                strident, iindex, false, context.netops));
    if (!jv.empty()) {
        for (json::value::const_iterator it(jv.begin()); it != jv.end(); ++it)
            result[it.membername()] = it.key();

        return result;
    }

    if (!ledger->hasaccount(rippleaddress))
        return rpcerror(rpcact_not_found);

    std::string strpeer(params.ismember(jss::peer) ? params[jss::peer].asstring() : "");
    bool bpeerindex(params.ismember(jss::peer_index));
    int ipeerindex(bindex ? params[jss::peer_index].asuint() : 0);
    rippleaddress rippleaddresspeer;

    json::value const jvpeer(rpc::accountfromstring(ledger, rippleaddresspeer, bpeerindex,
                                                    strpeer, ipeerindex, false, context.netops));
    if (!jvpeer.empty()) {
        return result;
    }

    if (!ledger->hasaccount(rippleaddresspeer))
        return rpcerror(rpcact_not_found);

    currency ucurrency;
    if (!to_currency(ucurrency, params[jss::currency].asstring()))
        return rpc::make_error(rpcsrc_cur_malformed, "invalid field 'currency', bad currency.");

    account const& raaccount(rippleaddress.getaccountid());
    account const& rapeeraccount(rippleaddresspeer.getaccountid());

    uint256 unodeindex = getripplestateindex(raaccount, rapeeraccount, ucurrency);
    auto slenode = context.netops.getslei(ledger, unodeindex);
    auto const line(ripplestate::makeitem(raaccount, slenode));

    if (line == nullptr ||
        raaccount != line->getaccountid() ||
        rapeeraccount != line->getaccountidpeer())
        return result;

    json::value jsonlines(json::arrayvalue);
    addline(jsonlines, *line, ledger);
    result[jss::lines] = jsonlines[0u];
    
    json::value& jsonassetstates(result[jss::states] = json::arrayvalue);
    
    // get asset_states for currency asset.
    if (assetcurrency() == line->getbalance().getcurrency()) {
        auto lpledger = std::make_shared<ledger> (std::ref (*ledger), false);
        ledgerentryset les(lpledger, tapnone);
        auto sleripplestate = les.entrycache(ltripple_state, getripplestateindex(raaccount, rapeeraccount, assetcurrency()));
        les.assetrelease(raaccount, rapeeraccount, assetcurrency(), sleripplestate);

        uint256 baseindex = getassetstateindex(line->getaccountid(), line->getaccountidpeer(), assetcurrency());
        uint256 assetstateindex = getqualityindex(baseindex);
        uint256 assetstateend = getqualitynext(assetstateindex);

        for (;;) {
            auto const& sle = les.entrycache(ltasset_state, assetstateindex);
            if (sle) {
                stamount amount = sle->getfieldamount(sfamount);
                stamount released = sle->getfieldamount(sfdeliveredamount);

                if (sle->getfieldaccount160(sfaccount) == line->getaccountidpeer()) {
                    amount.negate();
                    released.negate();
                }

                auto reserved = released ? amount - released : amount;

                json::value& state(jsonassetstates.append(json::objectvalue));
                state[jss::date] = static_cast<json::uint>(getquality(assetstateindex));
                state[jss::amount] = amount.gettext();
                state[jss::reserve] = reserved.gettext();
            }

            auto const nextassetstate(
                les.getnextledgerindex(assetstateindex, assetstateend));

            if (nextassetstate.iszero())
                break;

            assetstateindex = nextassetstate;
        }
    }

    context.loadtype = resource::feemediumburdenrpc;
    return result;
}
Ejemplo n.º 8
0
// {
//   account: account,
//   ledger_index_min: ledger_index  // optional, defaults to earliest
//   ledger_index_max: ledger_index, // optional, defaults to latest
//   binary: boolean,                // optional, defaults to false
//   forward: boolean,               // optional, defaults to false
//   limit: integer,                 // optional
//   marker: opaque                  // optional, resume previous query
// }
json::value doaccounttx (rpc::context& context)
{
    auto& params = context.params;

    rippleaddress   raaccount;
    int limit = params.ismember (jss::limit) ?
            params[jss::limit].asuint () : -1;
    bool bbinary = params.ismember ("binary") && params["binary"].asbool ();
    bool bforward = params.ismember ("forward") && params["forward"].asbool ();
    std::uint32_t   uledgermin;
    std::uint32_t   uledgermax;
    std::uint32_t   uvalidatedmin;
    std::uint32_t   uvalidatedmax;
    bool bvalidated = context.netops.getvalidatedrange (
        uvalidatedmin, uvalidatedmax);

    if (!bvalidated)
    {
        // don't have a validated ledger range.
        return rpcerror (rpclgr_idxs_invalid);
    }

    if (!params.ismember ("account"))
        return rpcerror (rpcinvalid_params);

    if (!raaccount.setaccountid (params["account"].asstring ()))
        return rpcerror (rpcact_malformed);

    context.loadtype = resource::feemediumburdenrpc;

    if (params.ismember ("ledger_index_min") ||
        params.ismember ("ledger_index_max"))
    {
        std::int64_t iledgermin  = params.ismember ("ledger_index_min")
                ? params["ledger_index_min"].asint () : -1;
        std::int64_t iledgermax  = params.ismember ("ledger_index_max")
                ? params["ledger_index_max"].asint () : -1;

        uledgermin  = iledgermin == -1 ? uvalidatedmin :
            ((iledgermin >= uvalidatedmin) ? iledgermin : uvalidatedmin);
        uledgermax  = iledgermax == -1 ? uvalidatedmax :
            ((iledgermax <= uvalidatedmax) ? iledgermax : uvalidatedmax);

        if (uledgermax < uledgermin)
            return rpcerror (rpclgr_idxs_invalid);
    }
    else
    {
        ledger::pointer l;
        json::value ret = rpc::lookupledger (params, l, context.netops);

        if (!l)
            return ret;

        uledgermin = uledgermax = l->getledgerseq ();
    }

    std::string txtype = "";
    if (params.ismember("tx_type"))
    {
        txtype = params["tx_type"].asstring();
        //check validation of tx_type, protect from sql injection
        try {
            txformats::getinstance().findtypebyname(txtype);
        } catch (...) {
            writelog (lswarning, accounttx) <<
            "invalide tx_type " << txtype;
            txtype = "";
            return rpcerror (rpcinvalid_params);
        }
    }
    
    json::value resumetoken;

    if (params.ismember(jss::marker))
         resumetoken = params[jss::marker];

#ifndef beast_debug

    try
    {
#endif
        json::value ret (json::objectvalue);

        ret["account"] = raaccount.humanaccountid ();
        json::value& jvtxns = (ret["transactions"] = json::arrayvalue);

        if (bbinary)
        {
            auto txns = context.netops.gettxsaccountb (
                raaccount, uledgermin, uledgermax, bforward, resumetoken, limit,
                context.role == role::admin, txtype);

            for (auto& it: txns)
            {
                json::value& jvobj = jvtxns.append (json::objectvalue);

                jvobj["tx_blob"] = std::get<0> (it);
                jvobj["meta"] = std::get<1> (it);

                std::uint32_t uledgerindex = std::get<2> (it);

                jvobj["ledger_index"] = uledgerindex;
                jvobj[jss::validated] = bvalidated &&
                    uvalidatedmin <= uledgerindex &&
                    uvalidatedmax >= uledgerindex;
            }
        }
        else
        {
            auto txns = context.netops.gettxsaccount (
                raaccount, uledgermin, uledgermax, bforward, resumetoken, limit,
                context.role == role::admin, txtype);

            for (auto& it: txns)
            {
                json::value& jvobj = jvtxns.append (json::objectvalue);

                if (it.first)
                    jvobj[jss::tx] = it.first->getjson (1);

                if (it.second)
                {
                    auto meta = it.second->getjson (1);
                    addpaymentdeliveredamount (meta, context, it.first, it.second);
                    jvobj[jss::meta] = meta;

                    std::uint32_t uledgerindex = it.second->getlgrseq ();

                    jvobj[jss::validated] = bvalidated &&
                        uvalidatedmin <= uledgerindex &&
                        uvalidatedmax >= uledgerindex;
                }

            }
        }

        //add information about the original query
        ret[jss::ledger_index_min] = uledgermin;
        ret[jss::ledger_index_max] = uledgermax;
        if (params.ismember (jss::limit))
            ret[jss::limit]        = limit;
        if (!resumetoken.isnull())
            ret[jss::marker] = resumetoken;

        return ret;
#ifndef beast_debug
    }
    catch (...)
    {
        return rpcerror (rpcinternal);
    }

#endif
}
Ejemplo n.º 9
0
// {
//   account: <account>|<account_public_key>
//   account_index: <number>        // optional, defaults to 0.
//   ledger_hash : <ledger>
//   ledger_index : <ledger_index>
//   limit: integer                 // optional
//   marker: opaque                 // optional, resume previous query
// }
json::value doaccountoffers (rpc::context& context)
{
    auto const& params (context.params);
    if (! params.ismember (jss::account))
        return rpc::missing_field_error ("account");

    ledger::pointer ledger;
    json::value result (rpc::lookupledger (params, ledger, context.netops));
    if (! ledger)
        return result;

    std::string strident (params[jss::account].asstring ());
    bool bindex (params.ismember (jss::account_index));
    int const iindex (bindex ? params[jss::account_index].asuint () : 0);
    rippleaddress rippleaddress;

    json::value const jv (rpc::accountfromstring (ledger, rippleaddress, bindex,
        strident, iindex, false, context.netops));
    if (! jv.empty ())
    {
        for (json::value::const_iterator it (jv.begin ()); it != jv.end (); ++it)
            result[it.membername ()] = it.key ();

        return result;
    }

    // get info on account.
    result[jss::account] = rippleaddress.humanaccountid ();

    if (bindex)
        result[jss::account_index] = iindex;

    if (! ledger->hasaccount (rippleaddress))
        return rpcerror (rpcact_not_found);

    unsigned int limit;
    if (params.ismember (jss::limit))
    {
        auto const& jvlimit (params[jss::limit]);
        if (! jvlimit.isintegral ())
            return rpc::expected_field_error ("limit", "unsigned integer");

        limit = jvlimit.isuint () ? jvlimit.asuint () :
            std::max (0, jvlimit.asint ());

        if (context.role != role::admin)
        {
            limit = std::max (rpc::tuning::minoffersperrequest,
                std::min (limit, rpc::tuning::maxoffersperrequest));
        }
    }
    else
    {
        limit = rpc::tuning::defaultoffersperrequest;
    }

    account const& raaccount (rippleaddress.getaccountid ());
    json::value& jsonoffers (result[jss::offers] = json::arrayvalue);
    std::vector <sle::pointer> offers;
    unsigned int reserve (limit);
    uint256 startafter;
    std::uint64_t starthint;

    if (params.ismember(jss::marker))
    {
        // we have a start point. use limit - 1 from the result and use the
        // very last one for the resume.
        json::value const& marker (params[jss::marker]);

        if (! marker.isstring ())
            return rpc::expected_field_error ("marker", "string");

        startafter.sethex (marker.asstring ());
        sle::pointer sleoffer (ledger->getslei (startafter));

        if (sleoffer == nullptr ||
            sleoffer->gettype () != ltoffer ||
            raaccount != sleoffer->getfieldaccount160 (sfaccount))
        {
            return rpcerror (rpcinvalid_params);
        }

        starthint = sleoffer->getfieldu64(sfownernode);

        // caller provided the first offer (startafter), add it as first result
        json::value& obj (jsonoffers.append (json::objectvalue));
        sleoffer->getfieldamount (sftakerpays).setjson (obj[jss::taker_pays]);
        sleoffer->getfieldamount (sftakergets).setjson (obj[jss::taker_gets]);
        obj[jss::seq] = sleoffer->getfieldu32 (sfsequence);
        obj[jss::flags] = sleoffer->getfieldu32 (sfflags);

        offers.reserve (reserve);
    }
    else
    {
        starthint = 0;
        // we have no start point, limit should be one higher than requested.
        offers.reserve (++reserve);
    }

    if (! ledger->visitaccountitems (raaccount, startafter, starthint, reserve,
        [&offers](sle::ref offer)
        {
            if (offer->gettype () == ltoffer)
            {
                offers.emplace_back (offer);
                return true;
            }

            return false;
        }))
    {
        return rpcerror (rpcinvalid_params);
    }

    if (offers.size () == reserve)
    {
        result[jss::limit] = limit;

        result[jss::marker] = to_string (offers.back ()->getindex ());
        offers.pop_back ();
    }

    for (auto const& offer : offers)
    {
        json::value& obj (jsonoffers.append (json::objectvalue));
        offer->getfieldamount (sftakerpays).setjson (obj[jss::taker_pays]);
        offer->getfieldamount (sftakergets).setjson (obj[jss::taker_gets]);
        obj[jss::seq] = offer->getfieldu32 (sfsequence);
        obj[jss::flags] = offer->getfieldu32 (sfflags);
    }

    context.loadtype = resource::feemediumburdenrpc;
    return result;
}
Ejemplo n.º 10
0
void
syncfinish(Syncpath *s)
{
	int iscomplete;
	Vtime *m;

	/*
	 * We need to figure out whether a and b are now
	 * up to date with respect to the other.  This state is
	 * stored in s->a.complete and s->b.complete.
	 * If a or b was complete or incomplete without 
	 * doing any work, these are already set.  Else they are -1.
	 * 
	 * If the sync failed, we map -1 to 0.
	 * If the sync succeeded, we map -1 to 1.
	 * 
	 * If the sync was one-way only, then the value
	 * of s->a.complete is incorrect but will not be used.
	 */
	iscomplete = (s->state == SyncDone);
	if(nop){
		s->a.complete = 0;
		s->b.complete = 0;
	}
	dbg(DbgSync, "syncfinish %P %d %d %d\n", s->p, iscomplete, s->a.complete, s->b.complete);
	if(s->a.complete == -1)
		s->a.complete = iscomplete;
	if(s->b.complete == -1)
		s->b.complete = iscomplete;

	dbg(DbgSync, "syncfinish %P %d %d\n", s->p, s->a.complete, s->b.complete);
	/*
	 * Update the sync time on the now synced systems.
	 * For a directory, propagate the mtime too.  
	 *
	 * BUG: I think that when we create a directory tree
	 * (meaning one of the ->state's is not SDir),
	 * we might not set the mtime properly.  Check this.
	 */
	if(s->b.complete){
		m = nil;
		/* BUG: why is this both instead of just one? */
		if(s->a.s->state==SDir && s->b.s->state==SDir)
			m = s->a.s->mtime;
		if(rpcaddtime(s->sync->rb, s->p, s->a.s->synctime, m) < 0){
			s->state = SyncError;
			s->err = rpcerror();
			s->b.complete = 0;
			s->a.complete = 0;
			goto Err;
		}
	}
	if(!s->sync->oneway && s->a.complete){
		m = nil;
		if(s->b.s->state==SDir && s->a.s->state==SDir)
			m = s->b.s->mtime;
		if(rpcaddtime(s->sync->ra, s->p, s->b.s->synctime, m) < 0){
			s->state = SyncError;
			s->err = rpcerror();
			s->a.complete = 0;
			goto Err;
		}
	}

Err:
	qsend(s->sync->finishq, s);
}