void Animation::parsePrefab(json::Value& val) { if(val.isMember("sequences") && !val["sequences"].empty()) { json::Value sequences = val["sequences"]; for(json::Value::iterator it = sequences.begin(); it != sequences.end(); ++it) { if(!(*it).isMember("start") || !(*it).isMember("end") || !(*it).isMember("fps")) { szerr << "Animation sequence definition must have start and end frame and fps value." << ErrorStream::error; continue; } sf::Uint32 start = (*it)["start"].asUInt(); sf::Uint32 end = (*it)["end"].asUInt(); sf::Uint32 fps = (*it)["fps"].asUInt(); bool looping = (*it).get("looping", 0).asBool(); std::string next = (*it).get("next", "").asString(); defineAnimation(it.memberName(), start, end, fps, looping, next); } } if(val.isMember("autoplay")) { if(val["autoplay"].isString()) { play(val["autoplay"].asString()); } } }
void Roster::update(const json::Value& data, bool whiny) { if (data.isObject() && data.isMember("id") && data.isMember("user") && data.isMember("name") //&& //data.isMember("type") ) { TraceS(this) << "Updating: " << json::stringify(data, true) << endl; std::string id = data["id"].asString(); Peer* peer = get(id, false); if (!peer) { peer = new Peer(data); add(id, peer); } else static_cast<json::Value&>(*peer) = data; } else if (data.isArray()) { for (auto it = data.begin(); it != data.end(); it++) { update(*it, whiny); } } else { std::string error("Bad presence data: " + json::stringify(data)); ErrorS(this) << error << endl; if (whiny) throw std::runtime_error(error); } }
/// Returns a Smooth-format manifest file std::string BuildManifest(std::string & MovieId, JSON::Value & metadata){ std::stringstream Result; Result << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; Result << "<SmoothStreamingMedia MajorVersion=\"2\" MinorVersion=\"0\" TimeScale=\"10000000\" Duration=\"" << metadata["lastms"].asInt() << "\">\n"; if (metadata.isMember("audio")){ Result << " <StreamIndex Type=\"audio\" QualityLevels=\"1\" Name=\"audio\" Chunks=\"" << metadata["keytime"].size() << "\" Url=\"Q({bitrate})/A({start time})\">\n"; Result << " <QualityLevel Index=\"0\" Bitrate=\"" << metadata["audio"]["bps"].asInt() * 8 << "\" CodecPrivateData=\""; Result << std::hex; for (int i = 0; i < metadata["audio"]["init"].asString().size(); i++){ Result << std::setfill('0') << std::setw(2) << std::right << (int)metadata["audio"]["init"].asString()[i]; } Result << std::dec; Result << "\" SamplingRate=\"" << metadata["audio"]["rate"].asInt() << "\" Channels=\"2\" BitsPerSample=\"16\" PacketSize=\"4\" AudioTag=\"255\" FourCC=\"AACL\" />\n"; for (int i = 0; i < metadata["keytime"].size() - 1; i++){ Result << " <c "; if (i == 0){ Result << "t=\"0\" "; } Result << "d=\"" << 10000 * (metadata["keytime"][i + 1].asInt() - metadata["keytime"][i].asInt()) << "\" />\n"; } Result << " <c d=\"" << 10000 * (metadata["lastms"].asInt() - metadata["keytime"][metadata["keytime"].size() - 1].asInt()) << "\" />\n"; Result << " </StreamIndex>\n"; } if (metadata.isMember("video")){ Result << " <StreamIndex Type=\"video\" QualityLevels=\"1\" Name=\"video\" Chunks=\"" << metadata["keytime"].size() << "\" Url=\"Q({bitrate})/V({start time})\" MaxWidth=\"" << metadata["video"]["width"].asInt() << "\" MaxHeight=\"" << metadata["video"]["height"].asInt() << "\" DisplayWidth=\"" << metadata["video"]["width"].asInt() << "\" DisplayHeight=\"" << metadata["video"]["height"].asInt() << "\">\n"; Result << " <QualityLevel Index=\"0\" Bitrate=\"" << metadata["video"]["bps"].asInt() * 8 << "\" CodecPrivateData=\""; MP4::AVCC avccbox; avccbox.setPayload(metadata["video"]["init"].asString()); std::string tmpString = avccbox.asAnnexB(); Result << std::hex; for (int i = 0; i < tmpString.size(); i++){ Result << std::setfill('0') << std::setw(2) << std::right << (int)tmpString[i]; } Result << std::dec; Result << "\" MaxWidth=\"" << metadata["video"]["width"].asInt() << "\" MaxHeight=\"" << metadata["video"]["height"].asInt() << "\" FourCC=\"AVC1\" />\n"; for (int i = 0; i < metadata["keytime"].size() - 1; i++){ Result << " <c "; if (i == 0){ Result << "t=\"0\" "; } Result << "d=\"" << 10000 * (metadata["keytime"][i + 1].asInt() - metadata["keytime"][i].asInt()) << "\" />\n"; } Result << " <c d=\"" << 10000 * (metadata["lastms"].asInt() - metadata["keytime"][metadata["keytime"].size() - 1].asInt()) << "\" />\n"; Result << " </StreamIndex>\n"; } Result << "</SmoothStreamingMedia>\n"; #if DEBUG >= 8 std::cerr << "Sending this manifest:" << std::endl << Result << std::endl; #endif return Result.str(); } //BuildManifest
///\brief Builds a bootstrap for use in HTTP Dynamic streaming. ///\param streamName The name of the stream. ///\param metadata The current metadata, used to generate the index. ///\param fragnum The index of the current fragment ///\return The generated bootstrap. std::string dynamicBootstrap(std::string & streamName, JSON::Value & metadata, int fragnum = 0){ std::string empty; MP4::ASRT asrt; asrt.setUpdate(false); asrt.setVersion(1); //asrt.setQualityEntry(empty, 0); if (metadata.isMember("live")){ asrt.setSegmentRun(1, 4294967295ul, 0); }else{ asrt.setSegmentRun(1, metadata["keytime"].size(), 0); } MP4::AFRT afrt; afrt.setUpdate(false); afrt.setVersion(1); afrt.setTimeScale(1000); //afrt.setQualityEntry(empty, 0); MP4::afrt_runtable afrtrun; if (metadata.isMember("live")){ // restrict data to last 2 fragments, unless an earlier fragment was expressly requested. int count = 0; unsigned int begin = std::max(0u, metadata["keynum"].size() - 3); while (begin > 0 && fragnum && metadata["keynum"][begin].asInt() > fragnum){ begin--; } for (int i = begin; i < metadata["keynum"].size(); i++){ afrtrun.firstFragment = metadata["keynum"][i].asInt(); afrtrun.firstTimestamp = metadata["keytime"][i].asInt(); afrtrun.duration = metadata["keylen"][i].asInt(); afrt.setFragmentRun(afrtrun, count++); } }else{ for (int i = 0; i < metadata["keynum"].size(); i++){ afrtrun.firstFragment = metadata["keynum"][i].asInt(); afrtrun.firstTimestamp = metadata["keytime"][i].asInt(); afrtrun.duration = metadata["keylen"][i].asInt(); afrt.setFragmentRun(afrtrun, i); } } MP4::ABST abst; abst.setVersion(1); abst.setBootstrapinfoVersion(1); abst.setProfile(0); abst.setUpdate(false); abst.setTimeScale(1000); abst.setLive(false); abst.setCurrentMediaTime(metadata["lastms"].asInt()); abst.setSmpteTimeCodeOffset(0); abst.setMovieIdentifier(streamName); abst.setSegmentRunTable(asrt, 0); abst.setFragmentRunTable(afrt, 0); #if DEBUG >= 8 std::cout << "Sending bootstrap:" << std::endl << abst.toPrettyString(0) << std::endl; #endif return std::string((char*)abst.asBox(), (int)abst.boxedSize()); }
/// Adds a single DTSC packet to the stream, updating the internal metadata if needed. void DTSC::Stream::addPacket(JSON::Value & newPack) { livePos newPos; newPos.trackID = newPack["trackid"].asInt(); newPos.seekTime = newPack["time"].asInt(); if (!metadata.tracks.count(newPos.trackID) && (!newPack.isMember("mark") || newPack["mark"].asStringRef() != "pause")) { return; } if (buffercount > 1 && metadata.tracks[newPos.trackID].keys.size() > 1 && newPos.seekTime < (long long unsigned int)metadata.tracks[newPos.trackID].keys.rbegin()->getTime()) { resetStream(); } while (buffers.count(newPos) > 0) { newPos.seekTime++; } while (buffercount == 1 && buffers.size() > 0) { cutOneBuffer(); } buffers[newPos] = newPack; datapointertype = INVALID; std::string tmp = ""; if (newPack.isMember("trackid") && newPack["trackid"].asInt() > 0) { tmp = metadata.tracks[newPack["trackid"].asInt()].type; } if (newPack.isMember("datatype")) { tmp = newPack["datatype"].asStringRef(); } if (tmp == "video") { datapointertype = VIDEO; } if (tmp == "audio") { datapointertype = AUDIO; } if (tmp == "meta") { datapointertype = META; } if (tmp == "pause_marker" || (newPack.isMember("mark") && newPack["mark"].asStringRef() == "pause")) { datapointertype = PAUSEMARK; } if (buffercount > 1) { metadata.update(newPack); if (newPack.isMember("keyframe") || (long long unsigned int)metadata.tracks[newPos.trackID].keys.rbegin()->getTime() == newPos.seekTime) { keyframes[newPos.trackID].insert(newPos); } metadata.live = true; //throw away buffers if buffer time is met int trid = buffers.begin()->first.trackID; int firstTime = buffers.begin()->first.seekTime; int lastTime = buffers.rbegin()->first.seekTime - buffertime; while ((!metadata.tracks[trid].keys.size() && firstTime < lastTime) || (metadata.tracks[trid].keys.size() && metadata.tracks[trid].keys.rbegin()->getTime() < lastTime) || (metadata.tracks[trid].keys.size() > 2 && metadata.tracks[trid].keys.rbegin()->getTime() - firstTime > buffertime)) { cutOneBuffer(); trid = buffers.begin()->first.trackID; firstTime = buffers.begin()->first.seekTime; } metadata.bufferWindow = buffertime; } }
///\brief Parse a given stream configuration. ///\param in The requested configuration. ///\param out The new configuration after parsing. void CheckStreams(JSON::Value & in, JSON::Value & out) { bool changed = false; //check for new streams and updates for (JSON::ObjIter jit = in.ObjBegin(); jit != in.ObjEnd(); jit++) { if (out.isMember(jit->first)) { if ( !streamsEqual(jit->second, out[jit->first])) { Log("STRM", std::string("Updated stream ") + jit->first); Util::Procs::Stop(jit->first); startStream(jit->first, jit->second); } } else { Log("STRM", std::string("New stream ") + jit->first); startStream(jit->first, jit->second); } } //check for deleted streams for (JSON::ObjIter jit = out.ObjBegin(); jit != out.ObjEnd(); jit++) { if ( !in.isMember(jit->first)) { Log("STRM", std::string("Deleted stream ") + jit->first); Util::Procs::Stop(jit->first); } } //update old-style configurations to new-style for (JSON::ObjIter jit = in.ObjBegin(); jit != in.ObjEnd(); jit++) { if (jit->second.isMember("channel")) { if ( !jit->second.isMember("source")) { jit->second["source"] = jit->second["channel"]["URL"]; } jit->second.removeMember("channel"); } if (jit->second.isMember("preset")) { jit->second.removeMember("preset"); } } out = in; }
void CheckStreams(JSON::Value & in, JSON::Value & out){ bool changed = false; for (JSON::ObjIter jit = in.ObjBegin(); jit != in.ObjEnd(); jit++){ if (out.isMember(jit->first)){ if ( !streamsEqual(jit->second, out[jit->first])){ Log("STRM", std::string("Updated stream ") + jit->first); Util::Procs::Stop(jit->first); startStream(jit->first, jit->second); } }else{ Log("STRM", std::string("New stream ") + jit->first); startStream(jit->first, jit->second); } } for (JSON::ObjIter jit = out.ObjBegin(); jit != out.ObjEnd(); jit++){ if ( !in.isMember(jit->first)){ Log("STRM", std::string("Deleted stream ") + jit->first); Util::Procs::Stop(jit->first); } } out = in; }
///\brief Builds an index file for HTTP Dynamic streaming. ///\param streamName The name of the stream. ///\param metadata The current metadata, used to generate the index. ///\return The index file for HTTP Dynamic Streaming. std::string dynamicIndex(std::string & streamName, JSON::Value & metadata){ std::string Result; if (metadata.isMember("vod")){ Result = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" "<manifest xmlns=\"http://ns.adobe.com/f4m/1.0\">\n" "<id>" + streamName + "</id>\n" "<width>" + metadata["video"]["width"].asString() + "</width>\n" "<height>" + metadata["video"]["height"].asString() + "</height>\n" "<duration>" + metadata["length"].asString() + ".000</duration>\n" "<mimeType>video/mp4</mimeType>\n" "<streamType>recorded</streamType>\n" "<deliveryType>streaming</deliveryType>\n" "<bootstrapInfo profile=\"named\" id=\"bootstrap1\">" + Base64::encode(dynamicBootstrap(streamName, metadata)) + "</bootstrapInfo>\n" "<media streamId=\"1\" bootstrapInfoId=\"bootstrap1\" url=\"" + streamName + "/\">\n" "<metadata>AgAKb25NZXRhRGF0YQMAAAk=</metadata>\n" "</media>\n" "</manifest>\n"; }else{ Result = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" "<manifest xmlns=\"http://ns.adobe.com/f4m/1.0\">\n" "<id>" + streamName + "</id>\n" "<dvrInfo windowDuration=\"" + metadata["buffer_window"].asString().substr(0, metadata["buffer_window"].asString().size() - 3) + "\"></dvrInfo>" "<mimeType>video/mp4</mimeType>\n" "<streamType>live</streamType>\n" "<deliveryType>streaming</deliveryType>\n" "<media url=\"" + streamName + "/\">\n" "<metadata>AgAKb25NZXRhRGF0YQMAAAk=</metadata>\n" "</media>\n" "<bootstrapInfo profile=\"named\" url=\"" + streamName + ".abst\" />\n" "</manifest>\n"; } #if DEBUG >= 8 std::cerr << "Sending this manifest:" << std::endl << Result << std::endl; #endif return Result; } //BuildManifest
std::pair<bool, Json::Value> ripplePathFind(RippleLineCache::pointer const& cache, RippleAddress const& raSrc, RippleAddress const& raDst, STAmount const& saDstAmount, Ledger::pointer const& lpLedger, Json::Value const& jvSrcCurrencies, boost::optional<Json::Value> const& contextPaths, int const& level) { FindPaths fp( cache, raSrc.getAccountID(), raDst.getAccountID(), saDstAmount, level, 4); // max paths Json::Value jvArray(Json::arrayValue); for (unsigned int i = 0; i != jvSrcCurrencies.size(); ++i) { Json::Value jvSource = jvSrcCurrencies[i]; Currency uSrcCurrencyID; Account uSrcIssuerID; if (!jvSource.isObject()) return std::make_pair(false, rpcError(rpcINVALID_PARAMS)); // Parse mandatory currency. if (!jvSource.isMember(jss::currency) || !to_currency( uSrcCurrencyID, jvSource[jss::currency].asString())) { WriteLog(lsINFO, RPCHandler) << "Bad currency."; return std::make_pair(false, rpcError(rpcSRC_CUR_MALFORMED)); } if (uSrcCurrencyID.isNonZero()) uSrcIssuerID = raSrc.getAccountID(); // Parse optional issuer. if (jvSource.isMember(jss::issuer) && ((!jvSource[jss::issuer].isString() || !to_issuer(uSrcIssuerID, jvSource[jss::issuer].asString())) || (uSrcIssuerID.isZero() != uSrcCurrencyID.isZero()) || (noAccount() == uSrcIssuerID))) { WriteLog(lsINFO, RPCHandler) << "Bad issuer."; return std::make_pair(false, rpcError(rpcSRC_ISR_MALFORMED)); } STPathSet spsComputed; if (contextPaths) { Json::Value pathSet = Json::objectValue; pathSet[jss::Paths] = contextPaths.get(); STParsedJSONObject paths("pathSet", pathSet); if (paths.object.get() == nullptr) return std::make_pair(false, paths.error); else { spsComputed = paths.object.get()->getFieldPathSet(sfPaths); WriteLog(lsTRACE, RPCHandler) << "ripple_path_find: Paths: " << spsComputed.getJson(0); } } STPath fullLiquidityPath; auto valid = fp.findPathsForIssue( { uSrcCurrencyID, uSrcIssuerID }, spsComputed, fullLiquidityPath); if (!valid) { WriteLog(lsWARNING, RPCHandler) << "ripple_path_find: No paths found."; } else { auto& issuer = isXRP(uSrcIssuerID) ? isXRP(uSrcCurrencyID) ? // Default to source account. xrpAccount() : Account(raSrc.getAccountID()) : uSrcIssuerID; // Use specifed issuer. STAmount saMaxAmount({ uSrcCurrencyID, issuer }, 1); saMaxAmount.negate(); LedgerEntrySet lesSandbox(lpLedger, tapNONE); auto rc = path::RippleCalc::rippleCalculate( lesSandbox, saMaxAmount, // --> Amount to send is unlimited // to get an estimate. saDstAmount, // --> Amount to deliver. raDst.getAccountID(), // --> Account to deliver to. raSrc.getAccountID(), // --> Account sending from. spsComputed); // --> Path set. WriteLog(lsWARNING, RPCHandler) << "ripple_path_find:" << " saMaxAmount=" << saMaxAmount << " saDstAmount=" << saDstAmount << " saMaxAmountAct=" << rc.actualAmountIn << " saDstAmountAct=" << rc.actualAmountOut; if (fullLiquidityPath.size() > 0 && (rc.result() == terNO_LINE || rc.result() == tecPATH_PARTIAL)) { WriteLog(lsDEBUG, PathRequest) << "Trying with an extra path element"; spsComputed.push_back(fullLiquidityPath); lesSandbox.clear(); rc = path::RippleCalc::rippleCalculate( lesSandbox, saMaxAmount, // --> Amount to send is unlimited // to get an estimate. saDstAmount, // --> Amount to deliver. raDst.getAccountID(), // --> Account to deliver to. raSrc.getAccountID(), // --> Account sending from. spsComputed); // --> Path set. WriteLog(lsDEBUG, PathRequest) << "Extra path element gives " << transHuman(rc.result()); } if (rc.result() == tesSUCCESS) { Json::Value jvEntry(Json::objectValue); STPathSet spsCanonical; // Reuse the expanded as it would need to be calcuated // anyway to produce the canonical. (At least unless we // make a direct canonical.) jvEntry[jss::source_amount] = rc.actualAmountIn.getJson(0); jvEntry[jss::paths_canonical] = Json::arrayValue; jvEntry[jss::paths_computed] = spsComputed.getJson(0); jvArray.append(jvEntry); } else { std::string strToken; std::string strHuman; transResultInfo(rc.result(), strToken, strHuman); WriteLog(lsDEBUG, RPCHandler) << "ripple_path_find: " << strToken << " " << strHuman << " " << spsComputed.getJson(0); } } } return std::make_pair(true, jvArray); }
/// This takes a "totals" request, and fills in the response data. /// /// \api /// `"totals"` requests take the form of: /// ~~~~~~~~~~~~~~~{.js} /// { /// //array of streamnames to accumulate. Empty means all. /// "streams": ["streama", "streamb", "streamc"], /// //array of protocols to accumulate. Empty means all. /// "protocols": ["HLS", "HSS"], /// //list of requested data fields. Empty means all. /// "fields": ["clients", "downbps", "upbps"], /// //unix timestamp of data start. Negative means X seconds ago. Empty means earliest available. /// "start": 1234567 /// //unix timestamp of data end. Negative means X seconds ago. Empty means latest available (usually 'now'). /// "end": 1234567 /// } /// ~~~~~~~~~~~~~~~ /// and are responded to as: /// ~~~~~~~~~~~~~~~{.js} /// { /// //unix timestamp of start of data. Always present, always absolute. /// "start": 1234567, /// //unix timestamp of end of data. Always present, always absolute. /// "end": 1234567, /// //array of actually represented data fields. /// "fields": [...] /// // Time between datapoints. Here: 10 points with each 5 seconds afterwards, followed by 10 points with each 1 second afterwards. /// "interval": [[10, 5], [10, 1]], /// //the data for the times as mentioned in the "interval" field, in the order they appear in the "fields" field. /// "data": [[x, y, z], [x, y, z], [x, y, z]] /// } /// ~~~~~~~~~~~~~~~ void Controller::fillTotals(JSON::Value & req, JSON::Value & rep){ //first, figure out the timestamps wanted long long int reqStart = 0; long long int reqEnd = 0; if (req.isMember("start")){ reqStart = req["start"].asInt(); } if (req.isMember("end")){ reqEnd = req["end"].asInt(); } //add the current time, if negative or zero. if (reqStart < 0){ reqStart += Util::epoch(); } if (reqStart == 0){ reqStart = Util::epoch() - STAT_CUTOFF; } if (reqEnd <= 0){ reqEnd += Util::epoch(); } //at this point, reqStart and reqEnd are the absolute timestamp. unsigned int fields = 0; //next, figure out the fields wanted if (req.isMember("fields") && req["fields"].size()){ for (JSON::ArrIter it = req["fields"].ArrBegin(); it != req["fields"].ArrEnd(); it++){ if ((*it).asStringRef() == "clients"){fields |= STAT_TOT_CLIENTS;} if ((*it).asStringRef() == "downbps"){fields |= STAT_TOT_BPS_DOWN;} if ((*it).asStringRef() == "upbps"){fields |= STAT_TOT_BPS_UP;} } } //select all, if none selected if (!fields){fields = STAT_TOT_ALL;} //figure out what streams are wanted std::set<std::string> streams; if (req.isMember("streams") && req["streams"].size()){ for (JSON::ArrIter it = req["streams"].ArrBegin(); it != req["streams"].ArrEnd(); it++){ streams.insert((*it).asStringRef()); } } //figure out what protocols are wanted std::set<std::string> protos; if (req.isMember("protocols") && req["protocols"].size()){ for (JSON::ArrIter it = req["protocols"].ArrBegin(); it != req["protocols"].ArrEnd(); it++){ protos.insert((*it).asStringRef()); } } //output the selected fields rep["fields"].null(); if (fields & STAT_TOT_CLIENTS){rep["fields"].append("clients");} if (fields & STAT_TOT_BPS_DOWN){rep["fields"].append("downbps");} if (fields & STAT_TOT_BPS_UP){rep["fields"].append("upbps");} //start data collection std::map<long long unsigned int, totalsData> totalsCount; //start with current connections if (curConns.size()){ for (std::map<unsigned long, statStorage>::iterator it = curConns.begin(); it != curConns.end(); it++){ //data present and wanted? insert it! if (it->second.log.size() > 1 && (it->second.log.rbegin()->first >= (unsigned long long)reqStart || it->second.log.begin()->first <= (unsigned long long)reqEnd) && (!streams.size() || streams.count(it->second.streamName)) && (!protos.size() || protos.count(it->second.connector))){ //keep track of the previous and current, starting at position 2 so there's always a delta down/up value. std::map<unsigned long long, statLog>::iterator pi = it->second.log.begin(); for (std::map<unsigned long long, statLog>::iterator li = ++(it->second.log.begin()); li != it->second.log.end(); li++){ if (li->first < (unsigned long long)reqStart || pi->first > (unsigned long long)reqEnd){ continue; } unsigned int diff = li->first - pi->first; unsigned int ddown = (li->second.down - pi->second.down) / diff; unsigned int dup = (li->second.up - pi->second.up) / diff; for (long long unsigned int t = pi->first; t < li->first; t++){ if (t >= (unsigned long long)reqStart && t <= (unsigned long long)reqEnd){ totalsCount[t].add(ddown, dup); } } pi = li;//set previous iterator to log iterator } } } } //look at history if (oldConns.size()){ for (std::map<unsigned long long int, statStorage>::iterator it = oldConns.begin(); it != oldConns.end(); it++){ //data present and wanted? insert it! if (it->second.log.size() > 1 && (it->second.log.rbegin()->first >= (unsigned long long)reqStart || it->second.log.begin()->first <= (unsigned long long)reqEnd) && (!streams.size() || streams.count(it->second.streamName)) && (!protos.size() || protos.count(it->second.connector))){ //keep track of the previous and current, starting at position 2 so there's always a delta down/up value. std::map<unsigned long long, statLog>::iterator pi = it->second.log.begin(); for (std::map<unsigned long long, statLog>::iterator li = ++(it->second.log.begin()); li != it->second.log.end(); li++){ if (li->first < (unsigned long long)reqStart || pi->first > (unsigned long long)reqEnd){ continue; } unsigned int diff = li->first - pi->first; unsigned int ddown = (li->second.down - pi->second.down) / diff; unsigned int dup = (li->second.up - pi->second.up) / diff; for (long long unsigned int t = pi->first; t < li->first; t++){ if (t >= (unsigned long long)reqStart && t <= (unsigned long long)reqEnd){ totalsCount[t].add(ddown, dup); } } pi = li;//set previous iterator to log iterator } } } } //output the data itself if (!totalsCount.size()){ //Oh noes! No data. We'll just reply with a bunch of nulls. rep["start"].null(); rep["end"].null(); rep["data"].null(); rep["interval"].null(); return; } //yay! We have data! rep["start"] = (long long)totalsCount.begin()->first; rep["end"] = (long long)totalsCount.rbegin()->first; rep["data"].null(); rep["interval"].null(); long long prevT = 0; JSON::Value i; for (std::map<long long unsigned int, totalsData>::iterator it = totalsCount.begin(); it != totalsCount.end(); it++){ JSON::Value d; if (fields & STAT_TOT_CLIENTS){d.append(it->second.clients);} if (fields & STAT_TOT_BPS_DOWN){d.append(it->second.downbps);} if (fields & STAT_TOT_BPS_UP){d.append(it->second.upbps);} rep["data"].append(d); if (prevT){ if (i.size() < 2){ i.append(1ll); i.append((long long)(it->first - prevT)); }else{ if (i[1u].asInt() != (long long)(it->first - prevT)){ rep["interval"].append(i); i[0u] = 1ll; i[1u] = (long long)(it->first - prevT); }else{ i[0u] = i[0u].asInt() + 1; } } } prevT = it->first; } if (i.size() > 1){ rep["interval"].append(i); i.null(); } //all done! return is by reference, so no need to return anything here. }
// VFALCO TODO This function should take a reference to the params, modify it // as needed, and then there should be a separate function to // submit the transaction. // Json::Value transactionSign ( Json::Value params, bool bSubmit, bool bFailHard, RPCDetail::LedgerFacade& ledgerFacade, Role role) { Json::Value jvResult; WriteLog (lsDEBUG, RPCHandler) << "transactionSign: " << params; if (! params.isMember ("secret")) return RPC::missing_field_error ("secret"); if (! params.isMember ("tx_json")) return RPC::missing_field_error ("tx_json"); RippleAddress naSeed; if (! naSeed.setSeedGeneric (params["secret"].asString ())) return RPC::make_error (rpcBAD_SEED, RPC::invalid_field_message ("secret")); Json::Value& tx_json (params ["tx_json"]); if (! tx_json.isObject ()) return RPC::object_field_error ("tx_json"); if (! tx_json.isMember ("TransactionType")) return RPC::missing_field_error ("tx_json.TransactionType"); std::string const sType = tx_json ["TransactionType"].asString (); if (! tx_json.isMember ("Account")) return RPC::make_error (rpcSRC_ACT_MISSING, RPC::missing_field_message ("tx_json.Account")); RippleAddress raSrcAddressID; if (! raSrcAddressID.setAccountID (tx_json["Account"].asString ())) return RPC::make_error (rpcSRC_ACT_MALFORMED, RPC::invalid_field_message ("tx_json.Account")); bool const verify = !(params.isMember ("offline") && params["offline"].asBool ()); if (!tx_json.isMember ("Sequence") && !verify) return RPC::missing_field_error ("tx_json.Sequence"); // Check for current ledger. if (verify && !getConfig ().RUN_STANDALONE && (ledgerFacade.getValidatedLedgerAge () > 120)) return rpcError (rpcNO_CURRENT); // Check for load. if (ledgerFacade.isLoadedCluster () && (role != Role::ADMIN)) return rpcError (rpcTOO_BUSY); ledgerFacade.snapshotAccountState (raSrcAddressID); if (verify) { if (!ledgerFacade.isValidAccount ()) { // If not offline and did not find account, error. WriteLog (lsDEBUG, RPCHandler) << "transactionSign: Failed to find source account " << "in current ledger: " << raSrcAddressID.humanAccountID (); return rpcError (rpcSRC_ACT_NOT_FOUND); } } autofill_fee (params, ledgerFacade, jvResult, role == Role::ADMIN); if (RPC::contains_error (jvResult)) return jvResult; if ("Payment" == sType) { auto e = signPayment( params, tx_json, raSrcAddressID, ledgerFacade, role); if (contains_error(e)) return e; } if (!tx_json.isMember ("Sequence")) tx_json["Sequence"] = ledgerFacade.getSeq (); if (!tx_json.isMember ("Flags")) tx_json["Flags"] = tfFullyCanonicalSig; if (verify) { if (!ledgerFacade.hasAccountRoot ()) // XXX Ignore transactions for accounts not created. return rpcError (rpcSRC_ACT_NOT_FOUND); } RippleAddress secret = RippleAddress::createSeedGeneric ( params["secret"].asString ()); RippleAddress masterGenerator = RippleAddress::createGeneratorPublic ( secret); RippleAddress masterAccountPublic = RippleAddress::createAccountPublic ( masterGenerator, 0); if (verify) { WriteLog (lsTRACE, RPCHandler) << "verify: " << masterAccountPublic.humanAccountID () << " : " << raSrcAddressID.humanAccountID (); auto const secretAccountID = masterAccountPublic.getAccountID(); if (raSrcAddressID.getAccountID () == secretAccountID) { if (ledgerFacade.accountMasterDisabled ()) return rpcError (rpcMASTER_DISABLED); } else if (!ledgerFacade.accountMatchesRegularKey (secretAccountID)) { return rpcError (rpcBAD_SECRET); } } STParsedJSONObject parsed ("tx_json", tx_json); if (!parsed.object.get()) { jvResult ["error"] = parsed.error ["error"]; jvResult ["error_code"] = parsed.error ["error_code"]; jvResult ["error_message"] = parsed.error ["error_message"]; return jvResult; } std::unique_ptr<STObject> sopTrans = std::move(parsed.object); sopTrans->setFieldVL ( sfSigningPubKey, masterAccountPublic.getAccountPublic ()); STTx::pointer stpTrans; try { stpTrans = std::make_shared<STTx> (*sopTrans); //WriteLog(lsINFO, RPCHandler) << "radar: before sign " << stpTrans->getFieldAmount(sfAmount); } catch (std::exception&) { return RPC::make_error (rpcINTERNAL, "Exception occurred during transaction"); } std::string reason; if (!passesLocalChecks (*stpTrans, reason)) return RPC::make_error (rpcINVALID_PARAMS, reason); if (params.isMember ("debug_signing")) { jvResult["tx_unsigned"] = strHex ( stpTrans->getSerializer ().peekData ()); jvResult["tx_signing_hash"] = to_string (stpTrans->getSigningHash ()); } // FIXME: For performance, transactions should not be signed in this code // path. RippleAddress naAccountPrivate = RippleAddress::createAccountPrivate ( masterGenerator, secret, 0); stpTrans->sign (naAccountPrivate); Transaction::pointer tpTrans; try { //WriteLog(lsINFO, RPCHandler) << "radar: after sign " << stpTrans->getFieldAmount(sfAmount); tpTrans = std::make_shared<Transaction>(stpTrans, Validate::NO); //WriteLog(lsINFO, RPCHandler) << "radar: after copy" << tpTrans->getSTransaction()->getFieldAmount(sfAmount); } catch (std::exception&) { return RPC::make_error (rpcINTERNAL, "Exception occurred during transaction"); } try { // FIXME: For performance, should use asynch interface. tpTrans = ledgerFacade.submitTransactionSync (tpTrans, role == Role::ADMIN, true, bFailHard, bSubmit); if (!tpTrans) { return RPC::make_error (rpcINTERNAL, "Unable to sterilize transaction."); } } catch (std::exception&) { return RPC::make_error (rpcINTERNAL, "Exception occurred during transaction submission."); } try { jvResult["tx_json"] = tpTrans->getJson (0); jvResult["tx_blob"] = strHex ( tpTrans->getSTransaction ()->getSerializer ().peekData ()); if (temUNCERTAIN != tpTrans->getResult ()) { std::string sToken; std::string sHuman; transResultInfo (tpTrans->getResult (), sToken, sHuman); jvResult["engine_result"] = sToken; jvResult["engine_result_code"] = tpTrans->getResult (); jvResult["engine_result_message"] = sHuman; } return jvResult; } catch (std::exception&) { return RPC::make_error (rpcINTERNAL, "Exception occurred during JSON handling."); } }
Animation AnimationBuilder::spawnJobs(std::string &err, int maxTime){ FractalLogger::getSingleton()->write(id, "Fractal Is Animated: Note Detailed progress not reported.\n"); FractalLogger::getSingleton()->write(id, "Building Animation Data...\n"); unsigned long genStart = time(NULL); Animation anim; anim.baseID = id; anim.timeStarted = genStart; if(maxTime > 0){ anim.timeMustStop = time(NULL) + maxTime; }else{ anim.timeMustStop = 0; } if(!p->getJson().isMember("anim") || !p->getJson()["anim"].isObject()){ err += "No JSON Object Anim\n"; return anim; } Json::Value animData = p->getJson()["anim"]; p->getJson()["anim"] = Json::ValueType::nullValue; p->getJson()["basic"]["anim"]["selected"] = "no"; if(!animData.isMember("frames") || !animData["frames"].isInt()){ err += "anim.frames does not exist or non-int\n"; return anim; } if(animData["frames"].asInt() < 1){ err += "anim.frames out of bounds\n"; return anim; } anim.frames = animData["frames"].asInt(); if(!animData.isMember("fps") || !animData["fps"].isInt()){ err += "anim.fps does not exist or non-int\n"; return anim; } if(animData["fps"].asInt() < 1){ err += "anim.fps out of bounds\n"; return anim; } anim.fps = animData["fps"].asInt(); if(!animData.isMember("keyframes") || !animData["keyframes"].isArray()){ err += "anim.keyframes does not exist or non-array\n"; return anim; } if(!SchemaManager::getSingleton()->validateAnimationParam(animData["keyframes"], anim.frames, err)){ err += "Keyframe Validation Reported Error(s)!\n"; return anim; } // first job will render frame one -- we need to render all others ParamsFile pnew(p->getJson().toStyledString(), false); // copy json data to interpolate buildAnimatedParams(animData, &pnew); for(int i=2; i<=anim.frames; i++){ pnew.getJson()["internal"]["thisframe"] = i; std::string savepath = DirectoryManager::getSingleton()->getRootDirectory()+"renders/"; savepath = concat(savepath, anim.baseID) + concat(".frame.", i) + ".job"; interpolateFrame(pnew, i); pnew.saveToFile(savepath); anim.frameQueue.push_back(savepath); } p->getJson()["internal"]["thisframe"] = 1; p->getJson()["anim"] = animData; p->getJson()["basic"]["anim"]["selected"] = "yes"; // restore it :D // finally revalidate the parameters in case we messed up err += SchemaManager::getSingleton()->validateParamaters(p->getJson()); if(err == ""){ genStart = time(NULL) - genStart; FractalLogger::getSingleton()->write(id, concat("Animation Data Built: Took ", (float)genStart/1000)+" seconds!\n"); } return anim; }
/// This takes a "clients" request, and fills in the response data. /// /// \api /// `"client"` requests take the form of: /// ~~~~~~~~~~~~~~~{.js} /// { /// //array of streamnames to accumulate. Empty means all. /// "streams": ["streama", "streamb", "streamc"], /// //array of protocols to accumulate. Empty means all. /// "protocols": ["HLS", "HSS"], /// //list of requested data fields. Empty means all. /// "fields": ["host", "stream", "protocol", "conntime", "position", "down", "up", "downbps", "upbps"], /// //unix timestamp of measuring moment. Negative means X seconds ago. Empty means now. /// "time": 1234567 /// } /// ~~~~~~~~~~~~~~~ /// and are responded to as: /// ~~~~~~~~~~~~~~~{.js} /// { /// //unix timestamp of data. Always present, always absolute. /// "time": 1234567, /// //array of actually represented data fields. /// "fields": [...] /// //for all clients, the data in the order they appear in the "fields" field. /// "data": [[x, y, z], [x, y, z], [x, y, z]] /// } /// ~~~~~~~~~~~~~~~ void Controller::fillClients(JSON::Value & req, JSON::Value & rep){ //first, figure out the timestamp wanted long long int reqTime = 0; if (req.isMember("time")){ reqTime = req["time"].asInt(); } //to make sure no nasty timing business takes place, we store the case "now" as a bool. bool now = (reqTime == 0); //add the current time, if negative or zero. if (reqTime <= 0){ reqTime += Util::epoch(); } //at this point, reqTime is the absolute timestamp. rep["time"] = reqTime; //fill the absolute timestamp unsigned int fields = 0; //next, figure out the fields wanted if (req.isMember("fields") && req["fields"].size()){ for (JSON::ArrIter it = req["fields"].ArrBegin(); it != req["fields"].ArrEnd(); it++){ if ((*it).asStringRef() == "host"){fields |= STAT_CLI_HOST;} if ((*it).asStringRef() == "stream"){fields |= STAT_CLI_STREAM;} if ((*it).asStringRef() == "protocol"){fields |= STAT_CLI_PROTO;} if ((*it).asStringRef() == "conntime"){fields |= STAT_CLI_CONNTIME;} if ((*it).asStringRef() == "position"){fields |= STAT_CLI_POSITION;} if ((*it).asStringRef() == "down"){fields |= STAT_CLI_DOWN;} if ((*it).asStringRef() == "up"){fields |= STAT_CLI_UP;} if ((*it).asStringRef() == "downbps"){fields |= STAT_CLI_BPS_DOWN;} if ((*it).asStringRef() == "upbps"){fields |= STAT_CLI_BPS_UP;} } } //select all, if none selected if (!fields){fields = STAT_CLI_ALL;} //figure out what streams are wanted std::set<std::string> streams; if (req.isMember("streams") && req["streams"].size()){ for (JSON::ArrIter it = req["streams"].ArrBegin(); it != req["streams"].ArrEnd(); it++){ streams.insert((*it).asStringRef()); } } //figure out what protocols are wanted std::set<std::string> protos; if (req.isMember("protocols") && req["protocols"].size()){ for (JSON::ArrIter it = req["protocols"].ArrBegin(); it != req["protocols"].ArrEnd(); it++){ protos.insert((*it).asStringRef()); } } //output the selected fields rep["fields"].null(); if (fields & STAT_CLI_HOST){rep["fields"].append("host");} if (fields & STAT_CLI_STREAM){rep["fields"].append("stream");} if (fields & STAT_CLI_PROTO){rep["fields"].append("protocol");} if (fields & STAT_CLI_CONNTIME){rep["fields"].append("conntime");} if (fields & STAT_CLI_POSITION){rep["fields"].append("position");} if (fields & STAT_CLI_DOWN){rep["fields"].append("down");} if (fields & STAT_CLI_UP){rep["fields"].append("up");} if (fields & STAT_CLI_BPS_DOWN){rep["fields"].append("downbps");} if (fields & STAT_CLI_BPS_UP){rep["fields"].append("upbps");} //output the data itself rep["data"].null(); //start with current connections if (curConns.size()){ for (std::map<unsigned long, statStorage>::iterator it = curConns.begin(); it != curConns.end(); it++){ unsigned long long time = reqTime; if (now){time = it->second.log.rbegin()->first;} //data present and wanted? insert it! if ((it->second.log.rbegin()->first >= time && it->second.log.begin()->first <= time) && (!streams.size() || streams.count(it->second.streamName)) && (!protos.size() || protos.count(it->second.connector))){ JSON::Value d; std::map<unsigned long long, statLog>::iterator statRef = it->second.log.lower_bound(time); std::map<unsigned long long, statLog>::iterator prevRef = --(it->second.log.lower_bound(time)); if (fields & STAT_CLI_HOST){d.append(it->second.host);} if (fields & STAT_CLI_STREAM){d.append(it->second.streamName);} if (fields & STAT_CLI_PROTO){d.append(it->second.connector);} if (fields & STAT_CLI_CONNTIME){d.append((long long)statRef->second.time);} if (fields & STAT_CLI_POSITION){d.append((long long)statRef->second.lastSecond);} if (fields & STAT_CLI_DOWN){d.append(statRef->second.down);} if (fields & STAT_CLI_UP){d.append(statRef->second.up);} if (fields & STAT_CLI_BPS_DOWN){ if (statRef != it->second.log.begin()){ unsigned int diff = statRef->first - prevRef->first; d.append((statRef->second.down - prevRef->second.down) / diff); }else{ d.append(statRef->second.down); } } if (fields & STAT_CLI_BPS_UP){ if (statRef != it->second.log.begin()){ unsigned int diff = statRef->first - prevRef->first; d.append((statRef->second.up - prevRef->second.up) / diff); }else{ d.append(statRef->second.up); } } rep["data"].append(d); } } } //if we're only interested in current, don't even bother looking at history if (now){ return; } //look at history if (oldConns.size()){ for (std::map<unsigned long long int, statStorage>::iterator it = oldConns.begin(); it != oldConns.end(); it++){ //data present and wanted? insert it! if ((it->second.log.rbegin()->first >= (unsigned long long)reqTime && it->second.log.begin()->first <= (unsigned long long)reqTime) && (!streams.size() || streams.count(it->second.streamName)) && (!protos.size() || protos.count(it->second.connector))){ JSON::Value d; std::map<unsigned long long, statLog>::iterator statRef = it->second.log.lower_bound(reqTime); std::map<unsigned long long, statLog>::iterator prevRef = --(it->second.log.lower_bound(reqTime)); if (fields & STAT_CLI_HOST){d.append(it->second.host);} if (fields & STAT_CLI_STREAM){d.append(it->second.streamName);} if (fields & STAT_CLI_PROTO){d.append(it->second.connector);} if (fields & STAT_CLI_CONNTIME){d.append((long long)statRef->second.time);} if (fields & STAT_CLI_POSITION){d.append((long long)statRef->second.lastSecond);} if (fields & STAT_CLI_DOWN){d.append(statRef->second.down);} if (fields & STAT_CLI_UP){d.append(statRef->second.up);} if (fields & STAT_CLI_BPS_DOWN){ if (statRef != it->second.log.begin()){ unsigned int diff = statRef->first - prevRef->first; d.append((statRef->second.down - prevRef->second.down) / diff); }else{ d.append(statRef->second.down); } } if (fields & STAT_CLI_BPS_UP){ if (statRef != it->second.log.begin()){ unsigned int diff = statRef->first - prevRef->first; d.append((statRef->second.up - prevRef->second.up) / diff); }else{ d.append(statRef->second.up); } } rep["data"].append(d); } } } //all done! return is by reference, so no need to return anything here. }
int DTSCMerge(int argc, char ** argv){ Util::Config conf = Util::Config(argv[0], PACKAGE_VERSION); conf.addOption("output", JSON::fromString("{\"arg_num\":1, \"arg\":\"string\", \"help\":\"Filename of the output file.\"}")); conf.addOption("input", JSON::fromString("{\"arg_num\":2, \"arg\":\"string\", \"help\":\"Filename of the first input file.\"}")); conf.addOption("[additional_inputs ...]", JSON::fromString("{\"arg_num\":3, \"default\":\"\", \"arg\":\"string\", \"help\":\"Filenames of any number of aditional inputs.\"}")); conf.parseArgs(argc, argv); DTSC::File outFile; JSON::Value meta; DTSC::Meta newMeta; std::map<std::string,std::map<int, int> > trackMapping; bool fullSort = true; std::map<std::string, DTSC::File> inFiles; std::map<std::string, DTSC::Meta> metaData; std::string outFileName = argv[1]; std::string tmpFileName; for (int i = 2; i < argc; i++){ tmpFileName = argv[i]; if (tmpFileName == outFileName){ fullSort = false; }else{ DTSC::File F(tmpFileName); if (!F.getMeta().isFixed()){ std::cerr << tmpFileName << " has not been run through DTSCFix yet." << std::endl; return 1; } inFiles[tmpFileName] = F; } } if (fullSort){ outFile = DTSC::File(outFileName, true); }else{ outFile = DTSC::File(outFileName); if ( !outFile.getMeta().isFixed()){ std::cerr << outFileName << " has not been run through DTSCFix yet." << std::endl; return 1; } meta = outFile.getMeta().toJSON(); newMeta = DTSC::Meta(meta); if (meta.isMember("tracks") && meta["tracks"].size() > 0){ for (JSON::ObjIter trackIt = meta["tracks"].ObjBegin(); trackIt != meta["tracks"].ObjEnd(); trackIt++){ int nxtMap = getNextFree(trackMapping); trackMapping[argv[1]].insert(std::pair<int,int>(trackIt->second["trackid"].asInt(),nxtMap)); newMeta.tracks[nxtMap].trackID = nxtMap; } } } std::multimap<int,keyframeInfo> allSorted; for (std::map<std::string,DTSC::File>::iterator it = inFiles.begin(); it != inFiles.end(); it++){ DTSC::Meta tmpMeta(it->second.getMeta()); for (std::map<int,DTSC::Track>::iterator trackIt = tmpMeta.tracks.begin(); trackIt != tmpMeta.tracks.end(); trackIt++){ long long int oldID = trackIt->first; long long int mappedID = getNextFree(trackMapping); trackMapping[it->first].insert(std::pair<int,int>(oldID,mappedID)); for (std::deque<DTSC::Key>::iterator keyIt = trackIt->second.keys.begin(); keyIt != trackIt->second.keys.end(); keyIt++){ keyframeInfo tmpInfo; tmpInfo.fileName = it->first; tmpInfo.trackID = oldID; tmpInfo.keyTime = keyIt->getTime(); tmpInfo.keyBPos = keyIt->getBpos(); tmpInfo.keyNum = keyIt->getNumber(); tmpInfo.keyLen = keyIt->getLength(); if ((keyIt + 1) != trackIt->second.keys.end()){ tmpInfo.endBPos = (keyIt + 1)->getBpos(); }else{ tmpInfo.endBPos = it->second.getBytePosEOF(); } allSorted.insert(std::pair<int,keyframeInfo>(keyIt->getTime(),tmpInfo)); } newMeta.tracks[mappedID] = trackIt->second; newMeta.tracks[mappedID].trackID = mappedID; newMeta.tracks[mappedID].reset(); } } if (fullSort){ meta.null(); meta["moreheader"] = 0ll; std::string tmpWrite = meta.toPacked(); outFile.writeHeader(tmpWrite,true); } std::set<int> trackSelector; for (std::multimap<int,keyframeInfo>::iterator sortIt = allSorted.begin(); sortIt != allSorted.end(); sortIt++){ trackSelector.clear(); trackSelector.insert(sortIt->second.trackID); inFiles[sortIt->second.fileName].selectTracks(trackSelector); inFiles[sortIt->second.fileName].seek_time(sortIt->second.keyTime); inFiles[sortIt->second.fileName].seekNext(); while (inFiles[sortIt->second.fileName].getPacket() && inFiles[sortIt->second.fileName].getBytePos() <= sortIt->second.endBPos && !inFiles[sortIt->second.fileName].reachedEOF()){ if (inFiles[sortIt->second.fileName].getPacket().getTrackId() == sortIt->second.trackID){ JSON::Value tmp = inFiles[sortIt->second.fileName].getPacket().toJSON(); tmp["trackid"] = trackMapping[sortIt->second.fileName][sortIt->second.trackID]; outFile.writePacket(tmp); } inFiles[sortIt->second.fileName].seekNext(); } } if (fullSort || (meta.isMember("merged") && meta["merged"])){ newMeta.merged = 1; }else{ newMeta.merged = 0; } std::string writeMeta = newMeta.toJSON().toPacked(); meta["moreheader"] = outFile.addHeader(writeMeta); writeMeta = meta.toPacked(); outFile.writeHeader(writeMeta); return 0; }
///\brief Reads a DTSC file and attempts to fix the metadata in it. ///\param conf The current configuration of the program. ///\return The return code for the fixed program. int DTSCFix(Util::Config & conf){ DTSC::File F(conf.getString("filename")); F.seek_bpos(0); F.parseNext(); JSON::Value oriheader = F.getJSON(); JSON::Value meta = F.getMeta(); JSON::Value pack; if ( !oriheader.isMember("moreheader")){ std::cerr << "This file is too old to fix - please reconvert." << std::endl; return 1; } if (DTSC::isFixed(meta) && !conf.getBool("force")){ std::cerr << "This file was already fixed or doesn't need fixing - cancelling." << std::endl; return 0; } meta.removeMember("isFixed"); meta.removeMember("keytime"); meta.removeMember("keybpos"); meta.removeMember("moreheader"); std::map<std::string,int> trackIDs; std::map<std::string,HeaderEntryDTSC> trackData; long long int nowpack = 0; std::string currentID; int nextFreeID = 0; for (JSON::ObjIter it = meta["tracks"].ObjBegin(); it != meta["tracks"].ObjEnd(); it++){ trackIDs.insert(std::pair<std::string,int>(it->first,it->second["trackid"].asInt())); trackData[it->first].type = it->second["type"].asString(); trackData[it->first].trackID = it->second["trackid"].asInt(); trackData[it->first].type = it->second["type"].asString(); if (it->second["trackid"].asInt() >= nextFreeID){ nextFreeID = it->second["trackid"].asInt() + 1; } it->second.removeMember("keylen"); it->second.removeMember("keybpos"); it->second.removeMember("frags"); it->second.removeMember("keytime"); it->second.removeMember("keynum"); it->second.removeMember("keydata"); it->second.removeMember("keyparts"); it->second.removeMember("keys"); } F.parseNext(); while ( !F.getJSON().isNull()){ currentID = ""; if (F.getJSON()["trackid"].asInt() == 0){ if (F.getJSON()["datatype"].asString() == "video"){ currentID = "video0"; if (trackData[currentID].trackID == 0){ trackData[currentID].trackID = nextFreeID++; } if (meta.isMember("video")){ meta["tracks"][currentID] = meta["video"]; meta.removeMember("video"); } trackData[currentID].type = F.getJSON()["datatype"].asString(); }else{ if (F.getJSON()["datatype"].asString() == "audio"){ currentID = "audio0"; if (trackData[currentID].trackID == 0){ trackData[currentID].trackID = nextFreeID++; } if (meta.isMember("audio")){ meta["tracks"][currentID] = meta["audio"]; meta.removeMember("audio"); } trackData[currentID].type = F.getJSON()["datatype"].asString(); }else{ //fprintf(stderr, "Found an unknown package with packetid 0 and datatype %s\n",F.getJSON()["datatype"].asString().c_str()); F.parseNext(); continue; } } }else{ for( std::map<std::string,int>::iterator it = trackIDs.begin(); it != trackIDs.end(); it++ ) { if( it->second == F.getJSON()["trackid"].asInt() ) { currentID = it->first; break; } } if( currentID == "" ) { //fprintf(stderr, "Found an unknown v2 packet with id %d\n", F.getJSON()["trackid"].asInt()); F.parseNext(); continue; //should create new track but this shouldnt be needed... } } if (F.getJSON()["time"].asInt() < trackData[currentID].firstms){ trackData[currentID].firstms = F.getJSON()["time"].asInt(); } if (F.getJSON()["time"].asInt() >= nowpack){ nowpack = F.getJSON()["time"].asInt(); } if (trackData[currentID].type == "video"){ if (F.getJSON().isMember("keyframe")){ int newNum = meta["tracks"][currentID]["keys"].size(); meta["tracks"][currentID]["keys"][newNum]["num"] = ++trackData[currentID].keynum; meta["tracks"][currentID]["keys"][newNum]["time"] = F.getJSON()["time"]; meta["tracks"][currentID]["keys"][newNum]["bpos"] = F.getLastReadPos(); if (meta["tracks"][currentID]["keys"].size() > 1){ meta["tracks"][currentID]["keys"][newNum - 1]["len"] = F.getJSON()["time"].asInt() - meta["tracks"][currentID]["keys"][newNum - 1]["time"].asInt(); meta["tracks"][currentID]["keys"][newNum - 1]["size"] = trackData[currentID].totalSize; trackData[currentID].totalSize = 0; std::string encodeVec = JSON::encodeVector( trackData[currentID].parts.begin(), trackData[currentID].parts.end() ); meta["tracks"][currentID]["keys"][newNum - 1]["parts"] = encodeVec; meta["tracks"][currentID]["keys"][newNum - 1]["partsize"] = (long long int)trackData[currentID].parts.size(); trackData[currentID].parts.clear(); } } }else{ if ((F.getJSON()["time"].asInt() - trackData[currentID].lastKeyTime) > 1000){ trackData[currentID].lastKeyTime = F.getJSON()["time"].asInt(); int newNum = meta["tracks"][currentID]["keys"].size(); meta["tracks"][currentID]["keys"][newNum]["num"] = ++trackData[currentID].keynum; meta["tracks"][currentID]["keys"][newNum]["time"] = F.getJSON()["time"]; meta["tracks"][currentID]["keys"][newNum]["bpos"] = F.getLastReadPos(); if (meta["tracks"][currentID]["keys"].size() > 1){ meta["tracks"][currentID]["keys"][newNum - 1]["len"] = F.getJSON()["time"].asInt() - meta["tracks"][currentID]["keys"][newNum - 1]["time"].asInt(); meta["tracks"][currentID]["keys"][newNum - 1]["size"] = trackData[currentID].totalSize; trackData[currentID].totalSize = 0; std::string encodeVec = JSON::encodeVector( trackData[currentID].parts.begin(), trackData[currentID].parts.end() ); meta["tracks"][currentID]["keys"][newNum - 1]["parts"] = encodeVec; meta["tracks"][currentID]["keys"][newNum - 1]["partsize"] = (long long int)trackData[currentID].parts.size(); trackData[currentID].parts.clear(); } } } trackData[currentID].totalSize += F.getJSON()["data"].asString().size(); trackData[currentID].lastms = nowpack; trackData[currentID].parts.push_back(F.getJSON()["data"].asString().size()); F.parseNext(); } long long int firstms = 0x7fffffff; long long int lastms = -1; for (std::map<std::string,HeaderEntryDTSC>::iterator it = trackData.begin(); it != trackData.end(); it++){ if (it->second.firstms < firstms){ firstms = it->second.firstms; } if (it->second.lastms > lastms){ lastms = it->second.lastms; } meta["tracks"][it->first]["firstms"] = it->second.firstms; meta["tracks"][it->first]["lastms"] = it->second.lastms; meta["tracks"][it->first]["length"] = (it->second.lastms - it->second.firstms) / 1000; if ( !meta["tracks"][it->first].isMember("bps")){ meta["tracks"][it->first]["bps"] = (long long int)(it->second.lastms / ((it->second.lastms - it->second.firstms) / 1000)); } if (it->second.trackID != 0){ meta["tracks"][it->first]["trackid"] = trackIDs[it->first]; }else{ meta["tracks"][it->first]["trackid"] = nextFreeID ++; } meta["tracks"][it->first]["type"] = it->second.type; int tmp = meta["tracks"][it->first]["keys"].size(); if (tmp > 0){ if (tmp > 1){ meta["tracks"][it->first]["keys"][tmp - 1]["len"] = it->second.lastms - meta["tracks"][it->first]["keys"][tmp - 2]["time"].asInt(); }else{ meta["tracks"][it->first]["keys"][tmp - 1]["len"] = it->second.lastms; } meta["tracks"][it->first]["keys"][tmp - 1]["size"] = it->second.totalSize; std::string encodeVec = JSON::encodeVector( trackData[it->first].parts.begin(), trackData[it->first].parts.end() ); meta["tracks"][it->first]["keys"][tmp - 1]["parts"] = encodeVec; meta["tracks"][it->first]["keys"][tmp - 1]["partsize"] = (long long int)trackData[it->first].parts.size(); }else{ meta["tracks"][it->first]["keys"][tmp]["len"] = it->second.lastms; meta["tracks"][it->first]["keys"][tmp]["size"] = it->second.totalSize; std::string encodeVec = JSON::encodeVector( trackData[it->first].parts.begin(), trackData[it->first].parts.end() ); meta["tracks"][it->first]["keys"][tmp]["parts"] = encodeVec; meta["tracks"][it->first]["keys"][tmp]["partsize"] = (long long int)trackData[it->first].parts.size(); meta["tracks"][it->first]["keys"][tmp]["time"] = it->second.firstms; } //calculate fragments meta["tracks"][it->first]["frags"].null(); long long int currFrag = -1; long long int maxBps = 0; for (JSON::ArrIter arrIt = meta["tracks"][it->first]["keys"].ArrBegin(); arrIt != meta["tracks"][it->first]["keys"].ArrEnd(); arrIt++) { if ((*arrIt)["time"].asInt() / 10000 > currFrag){ currFrag = (*arrIt)["time"].asInt() / 10000; long long int fragLen = 1; long long int fragDur = (*arrIt)["len"].asInt(); long long int fragSize = (*arrIt)["size"].asInt(); for (JSON::ArrIter it2 = arrIt + 1; it2 != meta["tracks"][it->first]["keys"].ArrEnd(); it2++){ if ((*it2)["time"].asInt() / 10000 > currFrag || (it2 + 1) == meta["tracks"][it->first]["keys"].ArrEnd()){ JSON::Value thisFrag; thisFrag["num"] = (*arrIt)["num"].asInt(); thisFrag["time"] = (*arrIt)["time"].asInt(); thisFrag["len"] = fragLen; thisFrag["dur"] = fragDur; thisFrag["size"] = fragSize; if (fragDur / 1000){ thisFrag["bps"] = fragSize / (fragDur / 1000); if (maxBps < (fragSize / (fragDur / 1000))){ maxBps = (fragSize / (fragDur / 999)); } } else { thisFrag["bps"] = 1; } meta["tracks"][it->first]["frags"].append(thisFrag); break; } fragLen ++; fragDur += (*it2)["len"].asInt(); fragSize += (*it2)["size"].asInt(); } } } meta["tracks"][it->first]["maxbps"] = maxBps; } meta["firstms"] = firstms; meta["lastms"] = lastms; meta["length"] = (lastms - firstms) / 1000; //append the revised header std::string loader = meta.toPacked(); long long int newHPos = F.addHeader(loader); if ( !newHPos){ std::cerr << "Failure appending new header." << std::endl; return -1; } //re-write the original header with information about the location of the new one oriheader["moreheader"] = newHPos; loader = oriheader.toPacked(); if (F.writeHeader(loader)){ return 0; }else{ std::cerr << "Failure rewriting header." << std::endl; return -1; } } //DTSCFix
///\brief Starts a single stream ///\param name The name of the stream ///\param data The corresponding configuration values. void startStream(std::string name, JSON::Value & data) { data["online"] = (std::string)"Checking..."; data.removeMember("error"); std::string URL; if (data.isMember("channel") && data["channel"].isMember("URL")) { URL = data["channel"]["URL"].asString(); } if (data.isMember("source")) { URL = data["source"].asString(); } std::string cmd1, cmd2, cmd3; if (URL == "") { Log("STRM", "Error for stream " + name + "! Source parameter missing."); data["error"] = "Missing source parameter!"; return; } if (URL.substr(0, 4) == "push") { std::string pusher = URL.substr(7); if (data.isMember("DVR") && data["DVR"].asInt() > 0) { data["DVR"] = data["DVR"].asInt(); cmd2 = "MistBuffer -t " + data["DVR"].asString() + " -s " + name + " " + pusher; } else { cmd2 = "MistBuffer -s " + name + " " + pusher; } Util::Procs::Start(name, Util::getMyPath() + cmd2); Log("BUFF", "(re)starting stream buffer " + name + " for push data from " + pusher); } else { if (URL.substr(0, 1) == "/") { struct stat fileinfo; if (stat(URL.c_str(), &fileinfo) != 0 || S_ISDIR(fileinfo.st_mode)) { Log("BUFF", "Warning for VoD stream " + name + "! File not found: " + URL); data["error"] = "Not found: " + URL; data["online"] = 0; return; } cmd1 = "cat " + URL; if (Util::epoch() - lastBuffer[name] > 5) { data["error"] = "Available"; data["online"] = 2; } else { data["online"] = 1; data.removeMember("error"); } return; //MistPlayer handles VoD } else { cmd1 = "ffmpeg -re -async 2 -i " + URL + " -f flv -"; cmd2 = "MistFLV2DTSC"; } if (data.isMember("DVR") && data["DVR"].asInt() > 0) { data["DVR"] = data["DVR"].asInt(); cmd3 = "MistBuffer -t " + data["DVR"].asString() + " -s " + name; } else { cmd3 = "MistBuffer -s " + name; } if (cmd2 != "") { Util::Procs::Start(name, cmd1, Util::getMyPath() + cmd2, Util::getMyPath() + cmd3); Log("BUFF", "(re)starting stream buffer " + name + " for ffmpeg data: " + cmd1); } else { Util::Procs::Start(name, cmd1, Util::getMyPath() + cmd3); Log("BUFF", "(re)starting stream buffer " + name + " using input file " + URL); } } }
static Json::Value signPayment( Json::Value const& params, Json::Value& tx_json, RippleAddress const& raSrcAddressID, RPCDetail::LedgerFacade& ledgerFacade, Role role) { RippleAddress dstAccountID; if (!tx_json.isMember ("Amount")) return RPC::missing_field_error ("tx_json.Amount"); STAmount amount; if (! amountFromJsonNoThrow (amount, tx_json ["Amount"])) return RPC::invalid_field_error ("tx_json.Amount"); if (!tx_json.isMember ("Destination")) return RPC::missing_field_error ("tx_json.Destination"); if (!dstAccountID.setAccountID (tx_json["Destination"].asString ())) return RPC::invalid_field_error ("tx_json.Destination"); if (tx_json.isMember ("Paths") && params.isMember ("build_path")) return RPC::make_error (rpcINVALID_PARAMS, "Cannot specify both 'tx_json.Paths' and 'build_path'"); if (!tx_json.isMember ("Paths") && tx_json.isMember ("Amount") && params.isMember ("build_path")) { // Need a ripple path. Currency uSrcCurrencyID; Account uSrcIssuerID; STAmount saSendMax; if (tx_json.isMember ("SendMax")) { if (! amountFromJsonNoThrow (saSendMax, tx_json ["SendMax"])) return RPC::invalid_field_error ("tx_json.SendMax"); } else { // If no SendMax, default to Amount with sender as issuer. saSendMax = amount; saSendMax.setIssuer (raSrcAddressID.getAccountID ()); } if (saSendMax.isNative () && amount.isNative ()) return RPC::make_error (rpcINVALID_PARAMS, "Cannot build XRP to XRP paths."); { LegacyPathFind lpf (role == Role::ADMIN); if (!lpf.isOk ()) return rpcError (rpcTOO_BUSY); STPathSet spsPaths; STPath fullLiquidityPath; bool valid = ledgerFacade.findPathsForOneIssuer ( dstAccountID, saSendMax.issue (), amount, getConfig ().PATH_SEARCH_OLD, 4, // iMaxPaths spsPaths, fullLiquidityPath); if (!valid) { WriteLog (lsDEBUG, RPCHandler) << "transactionSign: build_path: No paths found."; return rpcError (rpcNO_PATH); } WriteLog (lsDEBUG, RPCHandler) << "transactionSign: build_path: " << spsPaths.getJson (0); if (!spsPaths.empty ()) tx_json["Paths"] = spsPaths.getJson (0); } } return Json::Value(); }
void ParticleComponent::parsePrefab(json::Value& val) { if(val.isMember("texture")) { const std::string assetid = val["texture"].asString(); TextureAsset* asset = Asset::getTexture(assetid); if(asset) { //m_particleTexture.reset(new sf::Texture(*asset->getAsset())); m_particleSystem.reset(new thor::ParticleSystem(asset->getAsset())); createEmitter(); } else { szerr << "Prefab particle texture '" << assetid << "' could not be retrieved." << ErrorStream::error; } } if(val.isMember("emissionrate")) { setEmissionRate(static_cast<float>(val["emissionrate"].asDouble())); } if(val.isMember("lifetime")) { if(val["lifetime"].isArray() && val["lifetime"].size() == 2) { setLifetime( static_cast<float>(val["lifetime"][0U].asDouble()), static_cast<float>(val["lifetime"][1U].asDouble()) ); } else if(val["lifetime"].isArray() && val["lifetime"].size() == 1) { setLifetime( static_cast<float>(val["lifetime"][0U].asDouble()) ); } else if(!val["lifetime"].isArray()) { setLifetime(static_cast<float>(val["lifetime"].asDouble())); } else { szerr << "Invalid particle lifetime value in prefab." << ErrorStream::error; } } if(val.isMember("velocity")) { if(val["velocity"].isArray() && val["velocity"].size() == 2) { setVelocity(sf::Vector2f( static_cast<float>(val["velocity"][0U].asDouble()), static_cast<float>(val["velocity"][1U].asDouble()) )); } } if(val.isMember("rotation")) { if(val["rotation"].isArray() && val["rotation"].size() == 2) { setRotation( static_cast<float>(val["rotation"][0U].asDouble()), static_cast<float>(val["rotation"][1U].asDouble()) ); } else if(val["rotation"].isArray() && val["rotation"].size() == 1) { setRotation( static_cast<float>(val["rotation"][0U].asDouble()) ); } else if(!val["rotation"].isArray()) { setRotation(static_cast<float>(val["rotation"].asDouble())); } else { szerr << "Invalid particle rotation value in prefab." << ErrorStream::error; } } if(val.isMember("scale")) { if(val["scale"].isArray() && val["scale"].size() == 2) { setScale( static_cast<float>(val["scale"][0U].asDouble()), static_cast<float>(val["scale"][1U].asDouble()) ); } else if(val["scale"].isArray() && val["scale"].size() == 1) { setScale( static_cast<float>(val["scale"][0U].asDouble()) ); } else if(!val["scale"].isArray()) { setScale(static_cast<float>(val["scale"].asDouble())); } else { szerr << "Invalid particle scale value in prefab." << ErrorStream::error; } } if(val.isMember("rotationspeed")) { if(val["rotationspeed"].isArray() && val["rotationspeed"].size() == 2) { setRotationSpeed( static_cast<float>(val["rotationspeed"][0U].asDouble()), static_cast<float>(val["rotationspeed"][1U].asDouble()) ); } else if(val["rotationspeed"].isArray() && val["rotationspeed"].size() == 1) { setRotationSpeed( static_cast<float>(val["rotationspeed"][0U].asDouble()) ); } else if(!val["rotationspeed"].isArray()) { setRotationSpeed(static_cast<float>(val["rotationspeed"].asDouble())); } else { szerr << "Invalid particle rotationspeed value in prefab." << ErrorStream::error; } } if(val.isMember("affectors")) { json::Value affectors = val["affectors"]; for(json::Value::iterator it = affectors.begin(); it != affectors.end(); ++it) { const std::string affector = it.memberName(); if(affector == "fade") { addFadeAffector( static_cast<float>((*it)[0U].asDouble()), static_cast<float>((*it)[1U].asDouble()) ); } else if(affector == "scale") { addScaleAffector( static_cast<float>((*it)[0U].asDouble()), static_cast<float>((*it)[1U].asDouble()) ); } else if(affector == "force") { addForceAffector( static_cast<float>((*it)[0U].asDouble()), static_cast<float>((*it)[1U].asDouble()) ); } } } if(val.get("prewarm", 0).asBool()) { prewarm(); } if(val.isMember("shader")) { json::Value shader = val["shader"]; if(shader.isConvertibleTo(json::stringValue)) { setShader(shader.asString()); } else if(shader.isObject()) { setShader(shader["asset"].asString()); if(shader.isMember("param") && !shader["param"].empty()) { json::Value parameters = shader["param"]; for(json::Value::iterator it = parameters.begin(); it != parameters.end(); ++it) { const std::string name = it.memberName(); json::Value v = *it; if(v.isArray()) { switch(v.size()) { case 1: m_shaderAsset->getAsset()->setParameter(name, (float)v[0U].asDouble()); break; case 2: m_shaderAsset->getAsset()->setParameter(name, (float)v[0U].asDouble(), (float)v[1U].asDouble()); break; case 3: m_shaderAsset->getAsset()->setParameter(name, (float)v[0U].asDouble(), (float)v[1U].asDouble(), (float)v[2U].asDouble()); break; case 4: { m_shaderAsset->getAsset()->setParameter(name, (float)v[0U].asDouble(), (float)v[1U].asDouble(), (float)v[2U].asDouble(), (float)v[3U].asDouble()); break; } default: szerr << "Incorrect amount of parameter arguments in prefab." << ErrorStream::error; break; } } else if(v.isConvertibleTo(json::realValue)) { m_shaderAsset->getAsset()->setParameter(name, (float)v.asDouble()); } } } } } if(val.isMember("color")) { sf::Uint32 size = val["color"].size(); if(size == 3 || size == 4) { sf::Color color; color.r = static_cast<sf::Uint8>(val["color"][0U].asUInt()); color.g = static_cast<sf::Uint8>(val["color"][1U].asUInt()); color.b = static_cast<sf::Uint8>(val["color"][2U].asUInt()); if(size == 4) { color.a = static_cast<sf::Uint8>(val["color"][3U].asUInt()); } setColor(color); } } const std::string blend = val.get("blendmode", "alpha").asString(); if(blend == "alpha") { m_renderStates.blendMode = sf::BlendAlpha; } else if(blend == "additive") { m_renderStates.blendMode = sf::BlendAdd; } else if(blend == "multiply") { m_renderStates.blendMode = sf::BlendMultiply; } else if(blend == "none") { m_renderStates.blendMode = sf::BlendNone; } }
E131OutputData::E131OutputData(const Json::Value &config) : UDPOutputData(config), E131sequenceNumber(1), universeCount(1) { memset((char *) &e131Address, 0, sizeof(sockaddr_in)); e131Address.sin_family = AF_INET; e131Address.sin_port = htons(E131_DEST_PORT); universe = config["id"].asInt(); priority = config["priority"].asInt(); if (config.isMember("universeCount")) { universeCount = config["universeCount"].asInt(); } if (universeCount < 1) { universeCount = 1; } switch (type) { case 0: // Multicast ipAddress = ""; break; case 1: //UnicastAddress ipAddress = config["address"].asString(); break; } if (type == E131_TYPE_MULTICAST) { int UniverseOctet[2]; char sAddress[32]; UniverseOctet[0] = universe/256; UniverseOctet[1] = universe%256; sprintf(sAddress, "239.255.%d.%d", UniverseOctet[0],UniverseOctet[1]); e131Address.sin_addr.s_addr = inet_addr(sAddress); } else { bool isAlpha = false; for (int x = 0; x < ipAddress.length(); x++) { isAlpha |= isalpha(ipAddress[x]); } if (isAlpha) { struct hostent* uhost = gethostbyname(ipAddress.c_str()); if (!uhost) { LogErr(VB_CHANNELOUT, "Error looking up E1.31 hostname: %s\n", ipAddress.c_str()); valid = false; } else { e131Address.sin_addr.s_addr = *((unsigned long*)uhost->h_addr); } } else { e131Address.sin_addr.s_addr = inet_addr(ipAddress.c_str()); } } e131Iovecs.resize(universeCount * 2); e131Headers.resize(universeCount); for (int x = 0; x < universeCount; x++) { unsigned char *e131Buffer = (unsigned char *)malloc(E131_HEADER_LENGTH); e131Headers[x] = e131Buffer; memcpy(e131Buffer, E131header, E131_HEADER_LENGTH); int uni = universe + x; e131Buffer[E131_PRIORITY_INDEX] = priority; e131Buffer[E131_UNIVERSE_INDEX] = (char)(uni/256); e131Buffer[E131_UNIVERSE_INDEX+1] = (char)(uni%256); // Property Value Count e131Buffer[E131_COUNT_INDEX] = ((channelCount+1)/256); e131Buffer[E131_COUNT_INDEX+1] = ((channelCount+1)%256); // RLP Protocol flags and length int count = 638 - 16 - (512 - (channelCount)); e131Buffer[E131_RLP_COUNT_INDEX] = (count/256)+0x70; e131Buffer[E131_RLP_COUNT_INDEX+1] = count%256; // Framing Protocol flags and length count = 638 - 38 - (512 - (channelCount)); e131Buffer[E131_FRAMING_COUNT_INDEX] = (count/256)+0x70; e131Buffer[E131_FRAMING_COUNT_INDEX+1] = count%256; // DMP Protocol flags and length count = 638 - 115 - (512 - (channelCount)); e131Buffer[E131_DMP_COUNT_INDEX] = (count/256)+0x70; e131Buffer[E131_DMP_COUNT_INDEX+1] = count%256; // use scatter/gather for the packet. One IOV will contain // the header, the second will point into the raw channel data // and will be set at output time. This avoids any memcpy. e131Iovecs[x * 2].iov_base = e131Buffer; e131Iovecs[x * 2].iov_len = E131_HEADER_LENGTH; e131Iovecs[x * 2 + 1].iov_base = nullptr; e131Iovecs[x * 2 + 1].iov_len = channelCount; } }
SpriteComponent::SpriteComponent(GameObject* _parent, const Json::Value& json) : Component(_parent) { if (json.isMember("texture")) setTexture(json["texture"].asString()); }
ListDisposition ValidatorList::verify ( Json::Value& list, PublicKey& pubKey, std::string const& manifest, std::string const& blob, std::string const& signature) { auto m = Manifest::make_Manifest (beast::detail::base64_decode(manifest)); if (! m || ! publisherLists_.count (m->masterKey)) return ListDisposition::untrusted; pubKey = m->masterKey; auto const revoked = m->revoked(); auto const result = publisherManifests_.applyManifest ( std::move(*m)); if (revoked && result == ManifestDisposition::accepted) { removePublisherList (pubKey); publisherLists_.erase (pubKey); } if (revoked || result == ManifestDisposition::invalid) return ListDisposition::untrusted; auto const sig = strUnHex(signature); auto const data = beast::detail::base64_decode (blob); if (! sig.second || ! ripple::verify ( publisherManifests_.getSigningKey(pubKey), makeSlice(data), makeSlice(sig.first))) return ListDisposition::invalid; Json::Reader r; if (! r.parse (data, list)) return ListDisposition::invalid; if (list.isMember("sequence") && list["sequence"].isInt() && list.isMember("expiration") && list["expiration"].isInt() && list.isMember("validators") && list["validators"].isArray()) { auto const sequence = list["sequence"].asUInt(); auto const expiration = TimeKeeper::time_point{ TimeKeeper::duration{list["expiration"].asUInt()}}; if (sequence < publisherLists_[pubKey].sequence || expiration <= timeKeeper_.now()) return ListDisposition::stale; else if (sequence == publisherLists_[pubKey].sequence) return ListDisposition::same_sequence; } else { return ListDisposition::invalid; } return ListDisposition::accepted; }
void SpaceStation::LoadFromJson(const Json::Value &jsonObj, Space *space) { ModelBody::LoadFromJson(jsonObj, space); GetModel()->SetLabel(GetLabel()); if (!jsonObj.isMember("space_station")) throw SavedGameCorruptException(); Json::Value spaceStationObj = jsonObj["space_station"]; if (!spaceStationObj.isMember("ship_docking")) throw SavedGameCorruptException(); if (!spaceStationObj.isMember("ports")) throw SavedGameCorruptException(); if (!spaceStationObj.isMember("index_for_system_body")) throw SavedGameCorruptException(); if (!spaceStationObj.isMember("door_animation_step")) throw SavedGameCorruptException(); if (!spaceStationObj.isMember("door_animation_state")) throw SavedGameCorruptException(); m_oldAngDisplacement = 0.0; Json::Value shipDockingArray = spaceStationObj["ship_docking"]; if (!shipDockingArray.isArray()) throw SavedGameCorruptException(); m_shipDocking.reserve(shipDockingArray.size()); for (Uint32 i = 0; i < shipDockingArray.size(); i++) { m_shipDocking.push_back(shipDocking_t()); shipDocking_t &sd = m_shipDocking.back(); Json::Value shipDockingArrayEl = shipDockingArray[i]; if (!shipDockingArrayEl.isMember("index_for_body")) throw SavedGameCorruptException(); if (!shipDockingArrayEl.isMember("stage")) throw SavedGameCorruptException(); if (!shipDockingArrayEl.isMember("stage_pos")) throw SavedGameCorruptException(); if (!shipDockingArrayEl.isMember("from_pos")) throw SavedGameCorruptException(); if (!shipDockingArrayEl.isMember("from_rot")) throw SavedGameCorruptException(); sd.shipIndex = shipDockingArrayEl["index_for_body"].asInt(); sd.stage = shipDockingArrayEl["stage"].asInt(); sd.stagePos = StrToDouble(shipDockingArrayEl["stage_pos"].asString()); // For some reason stagePos was saved as a float in pre-JSON system (saved & loaded as double here). JsonToVector(&(sd.fromPos), shipDockingArrayEl, "from_pos"); JsonToQuaternion(&(sd.fromRot), shipDockingArrayEl, "from_rot"); } // retrieve each of the port details and bay IDs Json::Value portArray = spaceStationObj["ports"]; if (!portArray.isArray()) throw SavedGameCorruptException(); m_ports.reserve(portArray.size()); for (Uint32 i = 0; i < portArray.size(); i++) { m_ports.push_back(SpaceStationType::SPort()); SpaceStationType::SPort &port = m_ports.back(); Json::Value portArrayEl = portArray[i]; if (!portArrayEl.isMember("min_ship_size")) throw SavedGameCorruptException(); if (!portArrayEl.isMember("max_ship_size")) throw SavedGameCorruptException(); if (!portArrayEl.isMember("in_use")) throw SavedGameCorruptException(); if (!portArrayEl.isMember("bays")) throw SavedGameCorruptException(); port.minShipSize = portArrayEl["min_ship_size"].asInt(); port.maxShipSize = portArrayEl["max_ship_size"].asInt(); port.inUse = portArrayEl["in_use"].asBool(); Json::Value bayArray = portArrayEl["bays"]; if (!bayArray.isArray()) throw SavedGameCorruptException(); port.bayIDs.reserve(bayArray.size()); for (Uint32 j = 0; j < bayArray.size(); j++) { Json::Value bayArrayEl = bayArray[j]; if (!bayArrayEl.isMember("bay_id")) throw SavedGameCorruptException(); if (!bayArrayEl.isMember("name")) throw SavedGameCorruptException(); port.bayIDs.push_back(std::make_pair(bayArrayEl["bay_id"].asInt(), bayArrayEl["name"].asString())); } } m_sbody = space->GetSystemBodyByIndex(spaceStationObj["index_for_system_body"].asUInt()); m_doorAnimationStep = StrToDouble(spaceStationObj["door_animation_step"].asString()); m_doorAnimationState = StrToDouble(spaceStationObj["door_animation_state"].asString()); InitStation(); m_navLights->LoadFromJson(spaceStationObj); }
/** * Expected input: * { * alg: "aes", * mode: "cbc", * key: key data, * iv: iv data (16 bytes), * input: data to encrypt or decrypt * } * * Good output: * { * output: data * } */ Json::Value AES::crypt(const std::string & algorithm, Json::Value & args, bool isEncrypt) { if (!args.isMember("key")) { throw std::string("key missing"); } if (!args.isMember("input")) { throw std::string("input missing"); } if (!args.isMember("iv")) { throw std::string("iv missing"); } if (!args.isMember("mode")) { throw std::string("mode missing"); } std::string modeString( gsecrypto::util::lowerCaseRemoveDashes(args["mode"].asString())); if ("cbc" != modeString) { throw std::string("Only CBC currently supported"); } DataTracker input; getData(args["input"], input); DataTracker result(input.dataLen); if (input.dataLen == 0) { Json::Value toReturn; toReturn["output"] = toJson(result); return toReturn; } DataTracker keyBytes; getData(args["key"], keyBytes); switch( keyBytes.dataLen*8 ) { case 128: case 192: case 256: break; default: std::stringstream stream; stream << "Key Size: " << (keyBytes.dataLen*8) << " bits not supported."; throw stream.str(); } if( (input.dataLen % 16) != 0 ) { throw std::string("Input not multiple of 128 bits. Use padding."); } DataTracker iv; getData(args["iv"], iv); if( iv.dataLen != 16 ) { throw std::string("IV not 128 bits."); } int mode = SB_AES_CBC; AESParams params(*this, SB_AES_CBC, SB_AES_128_BLOCK_BITS, false); AESKey key(params, keyBytes); AESContext context(params, key, mode, iv); context.crypt(input, result, isEncrypt); Json::Value toReturn; toReturn["output"] = toJson(result); return toReturn; }
/* --------------------------------------------------------------------------- ** main ** -------------------------------------------------------------------------*/ int main(int argc, char* argv[]) { const char* turnurl = ""; const char* defaultlocalstunurl = "0.0.0.0:3478"; const char* localstunurl = NULL; const char* stunurl = "stun.l.google.com:19302"; int logLevel = rtc::LERROR; const char* webroot = "./html"; std::string sslCertificate; webrtc::AudioDeviceModule::AudioLayer audioLayer = webrtc::AudioDeviceModule::kPlatformDefaultAudio; std::string streamName; std::map<std::string,std::string> urlVideoList; std::map<std::string,std::string> urlAudioList; std::string nbthreads; std::string passwdFile; std::string publishFilter(".*"); std::string httpAddress("0.0.0.0:"); std::string httpPort = "8000"; const char * port = getenv("PORT"); if (port) { httpPort = port; } httpAddress.append(httpPort); int c = 0; while ((c = getopt (argc, argv, "hVv::" "c:H:w:T:A:C:" "t:S::s::" "a::q:" "n:u:U:")) != -1) { switch (c) { case 'H': httpAddress = optarg; break; case 'c': sslCertificate = optarg; break; case 'w': webroot = optarg; break; case 'T': nbthreads = optarg; break; case 'A': passwdFile = optarg; break; case 't': turnurl = optarg; break; case 'S': localstunurl = optarg ? optarg : defaultlocalstunurl; stunurl = localstunurl; break; case 's': localstunurl = NULL; stunurl = optarg ? optarg : defaultlocalstunurl; break; case 'a': audioLayer = optarg ? (webrtc::AudioDeviceModule::AudioLayer)atoi(optarg) : webrtc::AudioDeviceModule::kDummyAudio; break; case 'q': publishFilter = optarg ; break; case 'C': { Json::Value root; std::ifstream stream(optarg); stream >> root; if (root.isMember("urls")) { Json::Value urls = root["urls"]; for( auto it = urls.begin() ; it != urls.end() ; it++ ) { std::string name = it.key().asString(); Json::Value value = *it; if (value.isMember("video")) { urlVideoList[name]=value["video"].asString(); } if (value.isMember("audio")) { urlAudioList[name]=value["audio"].asString(); } } } break; } case 'n': streamName = optarg; break; case 'u': { if (!streamName.empty()) { urlVideoList[streamName]=optarg; } } break; case 'U': { if (!streamName.empty()) { urlAudioList[streamName]=optarg; } } break; case 'v': logLevel--; if (optarg) { logLevel-=strlen(optarg); } break; case 'V': std::cout << VERSION << std::endl; exit(0); break; case 'h': default: std::cout << argv[0] << " [-H http port] [-S[embeded stun address]] [-t [username:password@]turn_address] -[v[v]] [url1]...[urln]" << std::endl; std::cout << argv[0] << " [-H http port] [-s[externel stun address]] [-t [username:password@]turn_address] -[v[v]] [url1]...[urln]" << std::endl; std::cout << argv[0] << " -V" << std::endl; std::cout << "\t -v[v[v]] : verbosity" << std::endl; std::cout << "\t -V : print version" << std::endl; std::cout << "\t -H hostname:port : HTTP server binding (default " << httpAddress << ")" << std::endl; std::cout << "\t -w webroot : path to get files" << std::endl; std::cout << "\t -c sslkeycert : path to private key and certificate for HTTPS" << std::endl; std::cout << "\t -T nbthreads : number of threads for HTTP server" << std::endl; std::cout << "\t -A passwd : password file for HTTP server access" << std::endl; std::cout << "\t -S[stun_address] : start embeded STUN server bind to address (default " << defaultlocalstunurl << ")" << std::endl; std::cout << "\t -s[stun_address] : use an external STUN server (default " << stunurl << ")" << std::endl; std::cout << "\t -t[username:password@]turn_address : use an external TURN relay server (default disabled)" << std::endl; std::cout << "\t -a[audio layer] : spefify audio capture layer to use (default:" << audioLayer << ")" << std::endl; std::cout << "\t -n name -u videourl -U audiourl : register a stream with name using url" << std::endl; std::cout << "\t [url] : url to register in the source list" << std::endl; std::cout << "\t -C config.json : load urls from JSON config file" << std::endl; exit(0); } } while (optind<argc) { std::string url(argv[optind]); urlVideoList[url]=url; optind++; } rtc::LogMessage::LogToDebug((rtc::LoggingSeverity)logLevel); rtc::LogMessage::LogTimestamps(); rtc::LogMessage::LogThreads(); std::cout << "Logger level:" << rtc::LogMessage::GetLogToDebug() << std::endl; rtc::Thread* thread = rtc::Thread::Current(); rtc::InitializeSSL(); // webrtc server std::list<std::string> iceServerList; iceServerList.push_back(std::string("stun:")+stunurl); if (strlen(turnurl)) { iceServerList.push_back(std::string("turn:")+turnurl); } PeerConnectionManager webRtcServer(iceServerList, urlVideoList, urlAudioList, audioLayer, publishFilter); if (!webRtcServer.InitializePeerConnection()) { std::cout << "Cannot Initialize WebRTC server" << std::endl; } else { // http server std::vector<std::string> options; options.push_back("document_root"); options.push_back(webroot); options.push_back("access_control_allow_origin"); options.push_back("*"); options.push_back("listening_ports"); options.push_back(httpAddress); if (!sslCertificate.empty()) { options.push_back("ssl_certificate"); options.push_back(sslCertificate); } if (!nbthreads.empty()) { options.push_back("num_threads"); options.push_back(nbthreads); } if (!passwdFile.empty()) { options.push_back("global_auth_file"); options.push_back(passwdFile); } try { std::cout << "HTTP Listen at " << httpAddress << std::endl; HttpServerRequestHandler httpServer(&webRtcServer, options); // start STUN server if needed std::unique_ptr<cricket::StunServer> stunserver; if (localstunurl != NULL) { rtc::SocketAddress server_addr; server_addr.FromString(localstunurl); rtc::AsyncUDPSocket* server_socket = rtc::AsyncUDPSocket::Create(thread->socketserver(), server_addr); if (server_socket) { stunserver.reset(new cricket::StunServer(server_socket)); std::cout << "STUN Listening at " << server_addr.ToString() << std::endl; } } // mainloop thread->Run(); } catch (const CivetException & ex) { std::cout << "Cannot Initialize start HTTP server exception:" << ex.what() << std::endl; } } rtc::CleanupSSL(); return 0; }
void Client::onPresenceData(const json::Value& data, bool whiny) { TraceL << "Updating: " << json::stringify(data, true) << endl; if (data.isObject() && data.isMember("id") && data.isMember("user") && data.isMember("name") && data.isMember("online") //&& //data.isMember("type") ) { std::string id = data["id"].asString(); bool online = data["online"].asBool(); Peer* peer = _roster.get(id, false); if (online) { if (!peer) { peer = new Peer(data); _roster.add(id, peer); InfoL << "Peer connected: " << peer->address().toString() << endl; PeerConnected.emit(this, *peer); } else static_cast<json::Value&>(*peer) = data; } else { if (peer) { InfoL << "Peer disconnected: " << peer->address().toString() << endl; PeerDisconnected.emit(this, *peer); _roster.free(id); } else { WarnL << "Got peer disconnected for unknown peer: " << id << endl; } } } else { std::string error("Bad presence data: " + json::stringify(data)); ErrorL << error << endl; if (whiny) throw std::runtime_error(error); } #if 0 if (data.isObject() && data.isMember("id") && data.isMember("user") && data.isMember("name") //&& //data.isMember("type") ) { TraceL << "Updating: " << json::stringify(data, true) << endl; std::string id = data["id"].asString(); Peer* peer = get(id, false); if (!peer) { peer = new Peer(data); add(id, peer); } else static_cast<json::Value&>(*peer) = data; } else if (data.isArray()) { for (auto it = data.begin(); it != data.end(); it++) { onPresenceData(*it, whiny); } } else { std::string error("Bad presence data: " + json::stringify(data)); ErrorL << error << endl; if (whiny) throw std::runtime_error(error); } #endif }
void collect() { int ret; if (!first_) { prev_time_ = cur_time_; prev_node_info_ = cur_node_info_; } ret = ::clock_gettime(CLOCK_REALTIME, &cur_time_); if (-1 == ret) { std::ostringstream oss; oss << "Failed to get clock time info: " << std::strerror(errno); throw std::runtime_error(oss.str()); } // Get the CPU time used (in ns) ret = ::virDomainGetInfo(dom_, &cur_node_info_); if (-1 == ret) { std::ostringstream oss; oss << "Failed to get domain info: " << dcs::testbed::libvirt::detail::last_error(conn_); throw std::runtime_error(oss.str()); } if (first_) { first_ = false; prev_time_ = cur_time_; prev_node_info_ = cur_node_info_; cpu_util_ = 0; mem_util_ = 0; } else { bool ok = true; // Update CPU utilization stats const boost::uint64_t ns_elapsed = (cur_time_.tv_sec-prev_time_.tv_sec)*1.0e9+(cur_time_.tv_nsec-prev_time_.tv_nsec); const boost::uint64_t ns_used = cur_node_info_.cpuTime-prev_node_info_.cpuTime; const int nvcpus = dcs::testbed::libvirt::detail::num_vcpus(conn_, dom_, VIR_DOMAIN_VCPU_MAXIMUM); cpu_util_ = static_cast<double>(ns_used/static_cast<long double>(ns_elapsed)); cpu_util_ /= static_cast<double>(nvcpus); // Update RAM utilization stats const unsigned long cfg_max_mem = dcs::testbed::libvirt::detail::config_max_memory(conn_, dom_); const unsigned long cur_max_mem = dcs::testbed::libvirt::detail::max_memory(conn_, dom_); const unsigned long cur_mem = dcs::testbed::libvirt::detail::current_memory(conn_, dom_); ::virDomainMemoryStatStruct stats[VIR_DOMAIN_MEMORY_STAT_NR]; int nr_stats = ::virDomainMemoryStats(dom_, stats, VIR_DOMAIN_MEMORY_STAT_NR, VIR_DOMAIN_AFFECT_CURRENT); if (0 <= nr_stats) { // Currently libvirt offers these stats: // - ..._SWAP_IN: The total amount of data read from swap space (in kB). // - ..._SWAP_OUT: The total amount of memory written out to swap space (in kB). // - ..._MAJOR_FAULT: Number of page faults that have occured when a process makes a valid access to virtual memory that is not available, for which disk I/O is required. // - ..._MINOR_FAULT: Number of page faults that have occurred when a process makes a valid access to virtual memory that is not available, for which disk I/O is'nt required. // - ..._UNUSED: The amount of memory left completely unused by the system (in kB). Memory that is available but used for reclaimable caches should NOT be reported as free. // - ..._AVAILABLE: The total amount of usable memory as seen by the domain (in kB). This value may be less than the amount of memory assigned to the domain if a balloon driver is in use or if the guest OS does not initialize all assigned pages. // - ..._ACTUAL_BALLOON: Current balloon value (in KB). // - ..._RSS: Resident Set Size of the process running the domain (in kB). long double mem_avail = 0; for (int i = 0; i < nr_stats; ++i) { if (stats[i].tag == VIR_DOMAIN_MEMORY_STAT_AVAILABLE) { //std::cerr << "DEBUG> MEM available " << stats[i].val << std::endl; mem_avail = stats[i].val; } mem_util_ = static_cast<double>((cur_max_mem-mem_avail)/static_cast<long double>(cfg_max_mem)); } } else { //std::cerr << "DEBUG> CONFIG MAX MEM: " << cfg_max_mem << std::endl; //std::cerr << "DEBUG> CURRENT MAX MEM: " << cur_max_mem << std::endl; //std::cerr << "DEBUG> CURRENT MEM: " << cur_mem << std::endl; #ifdef DCS_TESTBED_SENSOR_HAVE_MEMINFO_SERVER try { namespace asio = boost::asio; std::string server_addr = dcs::testbed::libvirt::detail::domain_name(conn_, dom_); std::string server_port = DCS_TESTBED_SENSOR_MEMINFO_SERVER_PORT; //std::cerr << "Connecting to " << server_addr << " on port " << server_port << std::endl; asio::io_service io_service; asio::ip::tcp::resolver resolver(io_service); asio::ip::tcp::resolver::query query(server_addr, server_port); asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); asio::ip::tcp::socket socket(io_service); boost::asio::connect(socket, endpoint_iterator); std::ostringstream oss; for (;;) { boost::array<char, 1024> buf; boost::system::error_code error; const std::size_t len = socket.read_some(boost::asio::buffer(buf), error); if (error == boost::asio::error::eof) { break; // Connection closed cleanly by peer. } else if (error) { throw boost::system::system_error(error); // Some other error. } oss << std::string(buf.data(), len); } socket.close(); if (!oss.str().empty()) { boost::uint32_t sz; std::string meminfo; boost::tie(sz, meminfo) = detail::meminfo_unpack(oss.str().c_str()); //std::cerr << "DEBUG> MEMINFO: " << meminfo << std::endl; Json::Value root; // will contains the root value after parsing Json::Reader reader; bool parse_ok = reader.parse(meminfo, root); if (parse_ok) { long double mem_avail = 0; if (root.isMember("MemAvailable")) { std::istringstream iss; iss.str(root.get("MemAvailable", "").asString()); iss >> mem_avail; } else if (root.isMember("MemFree")) { long double mem_free = 0; std::istringstream iss; iss.str(root.get("MemFree", "").asString()); iss >> mem_free; long double mem_cache = 0; iss.str(root.get("Cached", "0").asString()); iss >> mem_cache; mem_avail = mem_free+mem_cache; } long double mem_tot = 0; if (root.isMember("MemTotal")) { std::istringstream iss; iss.str(root.get("MemTotal", "").asString()); iss >> mem_tot; } else {
///\brief Checks whether two streams are equal. ///\param one The first stream for the comparison. ///\param two The second stream for the comparison. ///\return True if the streams are equal, false otherwise. bool streamsEqual(JSON::Value & one, JSON::Value & two) { if ( !one.isMember("source") || !two.isMember("source") || one["source"] != two["source"]) { return false; } return true; }
void doClean (Json::Value const& params) { LedgerIndex minRange; LedgerIndex maxRange; getApp().getLedgerMaster().getFullValidatedRange (minRange, maxRange); { SharedState::Access state (m_state); state->maxRange = maxRange; state->minRange = minRange; state->checkNodes = false; state->fixTxns = false; state->failures = 0; /* JSON Parameters: All parameters are optional. By default the cleaner cleans things it thinks are necessary. This behavior can be modified using the following options supplied via JSON RPC: "ledger" A single unsigned integer representing an individual ledger to clean. "min_ledger", "max_ledger" Unsigned integers representing the starting and ending ledger numbers to clean. If unspecified, clean all ledgers. "full" A boolean. When set to true, means clean everything possible. "fix_txns" A boolean value indicating whether or not to fix the transactions in the database as well. "check_nodes" A boolean, when set to true means check the nodes. "stop" A boolean, when set to true informs the cleaner to gracefully stop its current activities if any cleaning is taking place. */ // Quick way to fix a single ledger if (params.isMember(jss::ledger)) { state->maxRange = params[jss::ledger].asUInt(); state->minRange = params[jss::ledger].asUInt(); state->fixTxns = true; state->checkNodes = true; } if (params.isMember(jss::max_ledger)) state->maxRange = params[jss::max_ledger].asUInt(); if (params.isMember(jss::min_ledger)) state->minRange = params[jss::min_ledger].asUInt(); if (params.isMember(jss::full)) state->fixTxns = state->checkNodes = params[jss::full].asBool(); if (params.isMember(jss::fix_txns)) state->fixTxns = params[jss::fix_txns].asBool(); if (params.isMember(jss::check_nodes)) state->checkNodes = params[jss::check_nodes].asBool(); if (params.isMember(jss::stop) && params[jss::stop].asBool()) state->minRange = state->maxRange = 0; } notify(); }
///\brief Debugging tool for DTSC data. /// /// Expects DTSC data in a file given on the command line, outputs human-readable information to stderr. ///\param conf The configuration parsed from the commandline. ///\return The return code of the analyser. int analyseDTSC(Util::Config conf){ DTSC::File F(conf.getString("filename")); JSON::Value meta = F.getMeta(); std::cout << meta.toPrettyString() << std::endl; JSON::Value pack; long long unsigned int firstpack = 0; long long unsigned int nowpack = 0; long long unsigned int lastaudio = 0; long long unsigned int lastvideo = 0; long long unsigned int lastkey = 0; long long unsigned int totalvideo = 0; long long unsigned int totalaudio = 0; long long unsigned int keyframes = 0; long long unsigned int key_min = 0xffffffff; long long unsigned int key_max = 0; long long unsigned int vid_min = 0xffffffff; long long unsigned int vid_max = 0; long long unsigned int aud_min = 0xffffffff; long long unsigned int aud_max = 0; long long unsigned int bfrm_min = 0xffffffff; long long unsigned int bfrm_max = 0; long long unsigned int bps = 0; F.seekNext(); while ( !F.getJSON().isNull()){ std::cout << F.getJSON().toPrettyString() << std::endl; nowpack = F.getJSON()["time"].asInt(); if (firstpack == 0){ firstpack = nowpack; } if (F.getJSON()["datatype"].asString() == "audio"){ if (lastaudio != 0 && (nowpack - lastaudio) != 0){ bps = F.getJSON()["data"].asString().size() / (nowpack - lastaudio); if (bps < aud_min){ aud_min = bps; } if (bps > aud_max){ aud_max = bps; } } totalaudio += F.getJSON()["data"].asString().size(); lastaudio = nowpack; } if (F.getJSON()["datatype"].asString() == "video"){ if (lastvideo != 0 && (nowpack - lastvideo) != 0){ bps = F.getJSON()["data"].asString().size() / (nowpack - lastvideo); if (bps < vid_min){ vid_min = bps; } if (bps > vid_max){ vid_max = bps; } } if (F.getJSON()["keyframe"].asInt() != 0){ if (lastkey != 0){ bps = nowpack - lastkey; if (bps < key_min){ key_min = bps; } if (bps > key_max){ key_max = bps; } } keyframes++; lastkey = nowpack; } if (F.getJSON()["offset"].asInt() != 0){ bps = F.getJSON()["offset"].asInt(); if (bps < bfrm_min){ bfrm_min = bps; } if (bps > bfrm_max){ bfrm_max = bps; } } totalvideo += F.getJSON()["data"].asString().size(); lastvideo = nowpack; } F.seekNext(); } std::cout << std::endl << "Summary:" << std::endl; meta["length"] = (long long int)((nowpack - firstpack) / 1000); if (meta.isMember("audio")){ meta["audio"]["bps"] = (long long int)(totalaudio / ((lastaudio - firstpack) / 1000)); std::cout << " Audio: " << meta["audio"]["codec"].asString() << std::endl; std::cout << " Bitrate: " << meta["audio"]["bps"].asInt() << std::endl; } if (meta.isMember("video")){ meta["video"]["bps"] = (long long int)(totalvideo / ((lastvideo - firstpack) / 1000)); meta["video"]["keyms"] = (long long int)((lastvideo - firstpack) / keyframes); if (meta["video"]["keyms"].asInt() - key_min > key_max - meta["video"]["keyms"].asInt()){ meta["video"]["keyvar"] = (long long int)(meta["video"]["keyms"].asInt() - key_min); }else{ meta["video"]["keyvar"] = (long long int)(key_max - meta["video"]["keyms"].asInt()); } std::cout << " Video: " << meta["video"]["codec"].asString() << std::endl; std::cout << " Bitrate: " << meta["video"]["bps"].asInt() << std::endl; std::cout << " Keyframes: " << meta["video"]["keyms"].asInt() << "~" << meta["video"]["keyvar"].asInt() << std::endl; std::cout << " B-frames: " << bfrm_min << " - " << bfrm_max << std::endl; } return 0; }
/** Fill in the fee on behalf of the client. This is called when the client does not explicitly specify the fee. The client may also put a ceiling on the amount of the fee. This ceiling is expressed as a multiplier based on the current ledger's fee schedule. JSON fields "Fee" The fee paid by the transaction. Omitted when the client wants the fee filled in. "fee_mult_max" A multiplier applied to the current ledger's transaction fee that caps the maximum the fee server should auto fill. If this optional field is not specified, then a default multiplier is used. @param tx The JSON corresponding to the transaction to fill in @param ledger A ledger for retrieving the current fee schedule @param result A JSON object for injecting error results, if any @param admin `true` if this is called by an administrative endpoint. */ static void autofill_fee ( Json::Value& request, RPCDetail::LedgerFacade& ledgerFacade, Json::Value& result, bool admin) { Json::Value& tx (request["tx_json"]); if (tx.isMember ("Fee")) return; std::uint64_t feeByTrans = 0; if (tx.isMember("TransactionType") && tx["TransactionType"].asString() == "Payment") { if (!tx.isMember("Destination")) { RPC::inject_error (rpcINVALID_PARAMS, "no destination account", result); return; } Config d; std::string dstAccountID = tx["Destination"].asString(); RippleAddress dstAddress; if (!dstAddress.setAccountID(dstAccountID)) { RPC::inject_error (rpcINVALID_PARAMS, "invalid account id", result); return; } //dst account not exist yet, charge a fix amount of fee(0.01) for creating if (!ledgerFacade.isAccountExist(dstAddress.getAccountID())) { feeByTrans = d.FEE_DEFAULT_CREATE; } //if currency is native(VRP/VBC), charge 1/1000 of transfer amount, //otherwise charge a fix amount of fee(0.001) if (tx.isMember("Amount")) { STAmount amount; if (!amountFromJsonNoThrow(amount, tx["Amount"])) { RPC::inject_error (rpcINVALID_PARAMS, "wrong amount format", result); return; } feeByTrans += amount.isNative() ? amount.getNValue() * d.FEE_DEFAULT_RATE_NATIVE : d.FEE_DEFAULT_NONE_NATIVE; } } int mult = Tuning::defaultAutoFillFeeMultiplier; if (request.isMember ("fee_mult_max")) { if (request["fee_mult_max"].isNumeric ()) { mult = request["fee_mult_max"].asInt(); } else { RPC::inject_error (rpcHIGH_FEE, RPC::expected_field_message ( "fee_mult_max", "a number"), result); return; } } // Default fee in fee units. std::uint64_t const feeDefault = getConfig().TRANSACTION_FEE_BASE; // Administrative endpoints are exempt from local fees. std::uint64_t const fee = ledgerFacade.scaleFeeLoad (feeDefault, admin); std::uint64_t const limit = mult * ledgerFacade.scaleFeeBase (feeDefault); if (fee > limit) { std::stringstream ss; ss << "Fee of " << fee << " exceeds the requested tx limit of " << limit; RPC::inject_error (rpcHIGH_FEE, ss.str(), result); return; } std::stringstream ss; ss << std::max(fee, feeByTrans); tx["Fee"] = ss.str(); }