Checkpoint; lotsa changes...

This commit is contained in:
Zach Fox 2017-10-06 15:18:39 -07:00
parent 1fa9bd8fc6
commit 59a6726af6
11 changed files with 186 additions and 101 deletions

View file

@ -29,7 +29,8 @@ const char* LOCAL_MODELS_PERSIST_FILE = "resources/models.svo";
EntityServer::EntityServer(ReceivedMessage& message) :
OctreeServer(message),
_entitySimulation(NULL)
_entitySimulation(NULL),
_dynamicDomainVerificationTimer(this)
{
DependencyManager::set<ResourceManager>();
DependencyManager::set<ResourceCacheSharedItems>();
@ -38,6 +39,9 @@ EntityServer::EntityServer(ReceivedMessage& message) :
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
packetReceiver.registerListenerForTypes({ PacketType::EntityAdd, PacketType::EntityEdit, PacketType::EntityErase, PacketType::EntityPhysics, PacketType::ChallengeOwnership },
this, "handleEntityPacket");
connect(&_dynamicDomainVerificationTimer, &QTimer::timeout, this, &EntityServer::startDynamicDomainVerification);
_dynamicDomainVerificationTimer.setSingleShot(true);
}
EntityServer::~EntityServer() {
@ -93,6 +97,8 @@ void EntityServer::beforeRun() {
connect(_pruneDeletedEntitiesTimer, SIGNAL(timeout()), this, SLOT(pruneDeletedEntities()));
const int PRUNE_DELETED_MODELS_INTERVAL_MSECS = 1 * 1000; // once every second
_pruneDeletedEntitiesTimer->start(PRUNE_DELETED_MODELS_INTERVAL_MSECS);
startDynamicDomainVerification();
}
void EntityServer::entityCreated(const EntityItem& newEntity, const SharedNodePointer& senderNode) {
@ -410,3 +416,57 @@ QString EntityServer::serverSubclassStats() {
return statsString;
}
void EntityServer::startDynamicDomainVerification() {
qCDebug(entities) << "Starting Dynamic Domain Verification...";
auto nodeList = DependencyManager::get<NodeList>();
QString thisDomainID = nodeList->getDomainHandler().getUUID().toString();
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
QHash<QString, EntityItemID> localMap(tree->getEntityCertificateIDMap());
QHashIterator<QString, EntityItemID> i(localMap);
qCDebug(entities) << localMap.size() << "entities in _entityCertificateIDMap";
while (i.hasNext()) {
i.next();
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest networkRequest;
networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
QUrl requestURL = NetworkingConstants::METAVERSE_SERVER_URL;
requestURL.setPath("/api/v1/commerce/proof_of_purchase_status");
QJsonObject request;
request["certificate_id"] = i.key();
networkRequest.setUrl(requestURL);
QNetworkReply* networkReply = NULL;
networkReply = networkAccessManager.get(networkRequest);
connect(networkReply, &QNetworkReply::finished, [=]() {
QJsonObject jsonObject = QJsonDocument::fromJson(networkReply->readAll()).object();
QJsonDocument doc(jsonObject);
qCDebug(entities) << "ZRF FIXME" << doc.toJson(QJsonDocument::Compact);
// ZRF FIXME!!!
//if (networkReply->error() == QNetworkReply::NoError) {
if (true) {
// ZRF FIXME!!!
//if (jsonObject["location"].toString() != thisDomainID) {
if (false) {
qCDebug(entities) << "invalid_reason not empty, deleting entity" << i.value();
tree->deleteEntity(i.value(), true);
}
} else {
qCDebug(entities) << "Call to proof_of_purchase_status endpoint failed; deleting entity" << i.value();
tree->deleteEntity(i.value(), true);
}
networkReply->deleteLater();
});
}
int nextInterval = qrand() % ((MAXIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS + 1) - MINIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS) + MINIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS;
qCDebug(entities) << "Restarting Dynamic Domain Verification timer for" << nextInterval / 1000 << "seconds";
_dynamicDomainVerificationTimer.start(nextInterval);
}

View file

@ -80,6 +80,13 @@ private:
QReadWriteLock _viewerSendingStatsLock;
QMap<QUuid, QMap<QUuid, ViewerSendingStats>> _viewerSendingStats;
//static const int MINIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS = 45 * 60 * 1000; // 45m
//static const int MAXIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS = 75 * 60 * 1000; // 1h15m
static const int MINIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS = 5 * 1000; // 5s
static const int MAXIMUM_DYNAMIC_DOMAIN_VERIFICATION_TIMER_MS = 10 * 1000; // 10s
QTimer _dynamicDomainVerificationTimer;
void startDynamicDomainVerification();
};
#endif // hifi_EntityServer_h

View file

@ -125,7 +125,7 @@ Rectangle {
id: notSetUpTimer;
interval: 200;
onTriggered: {
sendToScript({method: 'checkout_walletNotSetUp'});
sendToScript({method: 'checkout_walletNotSetUp', itemId: itemId});
}
}

View file

@ -78,6 +78,10 @@ Rectangle {
onInventoryResult: {
purchasesReceived = true;
if (root.pendingInventoryReply) {
inventoryTimer.start();
}
if (result.status !== 'success') {
console.log("Failed to get purchases", result.message);
} else {
@ -98,10 +102,6 @@ Rectangle {
previousPurchasesModel.append(inventoryResult);
buildFilteredPurchasesModel();
if (root.pendingInventoryReply) {
inventoryTimer.start();
}
}
root.pendingInventoryReply = false;
@ -112,7 +112,7 @@ Rectangle {
id: notSetUpTimer;
interval: 200;
onTriggered: {
sendToScript({method: 'checkout_walletNotSetUp'});
sendToScript({method: 'purchases_walletNotSetUp'});
}
}

View file

@ -176,6 +176,8 @@ Rectangle {
commerce.getWalletStatus();
} else if (msg.referrer === 'purchases') {
sendToScript({method: 'goToPurchases'});
} else {
sendToScript({method: 'goToMarketplaceItemPage', itemId: msg.referrer});
}
} else if (msg.method === 'walletSetup_raiseKeyboard') {
root.keyboardRaised = true;

View file

@ -710,7 +710,7 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer<ReceivedMessage> pack
bool Wallet::verifyOwnerChallenge(const QByteArray& encryptedText, const QString& publicKey, QString& decryptedText) {
// I have no idea how to do this yet, so here's some dummy code that may not even work.
decryptedText = QString("fail");
decryptedText = QString("success");
return true;
}

View file

@ -147,63 +147,63 @@ int EntityTree::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
if (bytesLeftToRead >= (int)(numberOfEntities * expectedBytesPerEntity)) {
for (uint16_t i = 0; i < numberOfEntities; i++) {
int bytesForThisEntity = 0;
EntityItemID entityItemID = EntityItemID::readEntityItemIDFromBuffer(dataAt, bytesLeftToRead);
EntityItemPointer entity = findEntityByEntityItemID(entityItemID);
EntityItemID entityItemID = EntityItemID::readEntityItemIDFromBuffer(dataAt, bytesLeftToRead);
EntityItemPointer entity = findEntityByEntityItemID(entityItemID);
if (entity) {
QString entityScriptBefore = entity->getScript();
QUuid parentIDBefore = entity->getParentID();
QString entityServerScriptsBefore = entity->getServerScripts();
quint64 entityScriptTimestampBefore = entity->getScriptTimestamp();
if (entity) {
QString entityScriptBefore = entity->getScript();
QUuid parentIDBefore = entity->getParentID();
QString entityServerScriptsBefore = entity->getServerScripts();
quint64 entityScriptTimestampBefore = entity->getScriptTimestamp();
bytesForThisEntity = entity->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args);
if (entity->getDirtyFlags()) {
entityChanged(entity);
}
_entityMover.addEntityToMoveList(entity, entity->getQueryAACube());
bytesForThisEntity = entity->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args);
if (entity->getDirtyFlags()) {
entityChanged(entity);
}
_entityMover.addEntityToMoveList(entity, entity->getQueryAACube());
QString entityScriptAfter = entity->getScript();
QString entityServerScriptsAfter = entity->getServerScripts();
quint64 entityScriptTimestampAfter = entity->getScriptTimestamp();
bool reload = entityScriptTimestampBefore != entityScriptTimestampAfter;
QString entityScriptAfter = entity->getScript();
QString entityServerScriptsAfter = entity->getServerScripts();
quint64 entityScriptTimestampAfter = entity->getScriptTimestamp();
bool reload = entityScriptTimestampBefore != entityScriptTimestampAfter;
// If the script value has changed on us, or it's timestamp has changed to force
// a reload then we want to send out a script changing signal...
if (reload || entityScriptBefore != entityScriptAfter) {
emitEntityScriptChanging(entityItemID, reload); // the entity script has changed
}
if (reload || entityServerScriptsBefore != entityServerScriptsAfter) {
emitEntityServerScriptChanging(entityItemID, reload); // the entity server script has changed
}
// If the script value has changed on us, or it's timestamp has changed to force
// a reload then we want to send out a script changing signal...
if (reload || entityScriptBefore != entityScriptAfter) {
emitEntityScriptChanging(entityItemID, reload); // the entity script has changed
}
if (reload || entityServerScriptsBefore != entityServerScriptsAfter) {
emitEntityServerScriptChanging(entityItemID, reload); // the entity server script has changed
}
QUuid parentIDAfter = entity->getParentID();
if (parentIDBefore != parentIDAfter) {
addToNeedsParentFixupList(entity);
}
} else {
entity = EntityTypes::constructEntityItem(dataAt, bytesLeftToRead, args);
if (entity) {
bytesForThisEntity = entity->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args);
QUuid parentIDAfter = entity->getParentID();
if (parentIDBefore != parentIDAfter) {
addToNeedsParentFixupList(entity);
}
} else {
entity = EntityTypes::constructEntityItem(dataAt, bytesLeftToRead, args);
if (entity) {
bytesForThisEntity = entity->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args);
// don't add if we've recently deleted....
if (!isDeletedEntity(entityItemID)) {
_entitiesToAdd.insert(entityItemID, entity);
// don't add if we've recently deleted....
if (!isDeletedEntity(entityItemID)) {
_entitiesToAdd.insert(entityItemID, entity);
if (entity->getCreated() == UNKNOWN_CREATED_TIME) {
entity->recordCreationTime();
}
#ifdef WANT_DEBUG
} else {
qCDebug(entities) << "Received packet for previously deleted entity [" <<
entityItemID << "] ignoring. (inside " << __FUNCTION__ << ")";
#endif
}
}
}
// Move the buffer forward to read more entities
dataAt += bytesForThisEntity;
bytesLeftToRead -= bytesForThisEntity;
bytesRead += bytesForThisEntity;
if (entity->getCreated() == UNKNOWN_CREATED_TIME) {
entity->recordCreationTime();
}
#ifdef WANT_DEBUG
} else {
qCDebug(entities) << "Received packet for previously deleted entity [" <<
entityItemID << "] ignoring. (inside " << __FUNCTION__ << ")";
#endif
}
}
}
// Move the buffer forward to read more entities
dataAt += bytesForThisEntity;
bytesLeftToRead -= bytesForThisEntity;
bytesRead += bytesForThisEntity;
}
}
}
@ -214,13 +214,13 @@ int EntityTree::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
bool EntityTree::handlesEditPacketType(PacketType packetType) const {
// we handle these types of "edit" packets
switch (packetType) {
case PacketType::EntityAdd:
case PacketType::EntityEdit:
case PacketType::EntityErase:
case PacketType::EntityPhysics:
return true;
default:
return false;
case PacketType::EntityAdd:
case PacketType::EntityEdit:
case PacketType::EntityErase:
case PacketType::EntityPhysics:
return true;
default:
return false;
}
}
@ -241,6 +241,29 @@ void EntityTree::postAddEntity(EntityItemPointer entity) {
// find and hook up any entities with this entity as a (previously) missing parent
fixupNeedsParentFixups();
if (getIsServer()) {
QString certID(entity->getCertificateID());
EntityItemID entityItemID = entity->getEntityItemID();
EntityItemID existingEntityItemID;
{
QWriteLocker locker(&_entityCertificateIDMapLock);
existingEntityItemID = _entityCertificateIDMap.value(certID);
if (!certID.isEmpty()) {
_entityCertificateIDMap.insert(certID, entityItemID);
qCDebug(entities) << "Certificate ID" << certID << "belongs to" << entityItemID;
}
}
// Delete an already-existing entity from the tree if it has the same
// CertificateID as the entity we're trying to add.
if (!existingEntityItemID.isNull()) {
qCDebug(entities) << "Certificate ID" << certID << "already exists on entity with ID"
<< existingEntityItemID << ". Deleting existing entity.";
deleteEntity(existingEntityItemID, true);
}
}
}
bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties, const SharedNodePointer& senderNode) {
@ -654,8 +677,16 @@ void EntityTree::processRemovedEntities(const DeleteEntityOperator& theOperator)
theEntity->die();
if (getIsServer()) {
{
QWriteLocker entityCertificateIDMapLocker(&_entityCertificateIDMapLock);
QString certID = theEntity->getCertificateID();
if (theEntity->getEntityItemID() == _entityCertificateIDMap.value(certID)) {
_entityCertificateIDMap.remove(certID);
}
}
// set up the deleted entities ID
QWriteLocker locker(&_recentlyDeletedEntitiesLock);
QWriteLocker recentlyDeletedEntitiesLocker(&_recentlyDeletedEntitiesLock);
_recentlyDeletedEntityItemIDs.insert(deletedAt, theEntity->getEntityItemID());
} else {
// on the client side, we also remember that we deleted this entity, we don't care about the time
@ -665,9 +696,6 @@ void EntityTree::processRemovedEntities(const DeleteEntityOperator& theOperator)
if (_simulation) {
_simulation->prepareEntityForDelete(theEntity);
}
QWriteLocker locker(&_entityCertificateIDMapLock);
_entityCertificateIDMap.remove(theEntity->getProperties(PROP_CERTIFICATE_ID).getCertificateID());
}
}
@ -1117,8 +1145,8 @@ void EntityTree::startChallengeOwnershipTimer(const EntityItemID& entityItemID)
_challengeOwnershipTimeoutTimer->deleteLater();
}
});
_challengeOwnershipTimeoutTimer->setInterval(5000);
_challengeOwnershipTimeoutTimer->start();
_challengeOwnershipTimeoutTimer->setSingleShot(true);
_challengeOwnershipTimeoutTimer->start(5000);
}
void EntityTree::processChallengeOwnershipPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) {
@ -1346,7 +1374,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
endCreate = usecTimestampNow();
_totalCreates++;
if (newEntity && isCertified) {
if (newEntity && isCertified && getIsServer()) {
if (!newEntity->verifyStaticCertificateProperties()) {
qCDebug(entities) << "User" << senderNode->getUUID()
<< "attempted to add a certified entity with ID" << entityItemID << "which failed"
@ -1357,28 +1385,6 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
_recentlyDeletedEntityItemIDs.insert(usecTimestampNow(), entityItemID);
} else {
QString certID = properties.getCertificateID();
EntityItemID existingEntityItemID;
{
QReadLocker locker(&_entityCertificateIDMapLock);
existingEntityItemID = _entityCertificateIDMap.value(certID);
}
// Delete an already-existing entity from the tree if it has the same
// CertificateID as the entity we're trying to add.
if (!existingEntityItemID.isNull()) {
qCDebug(entities) << "Certificate ID" << certID << "already exists on entity with ID"
<< existingEntityItemID << ". Deleting existing entity.";
deleteEntity(existingEntityItemID, true);
QWriteLocker locker(&_recentlyDeletedEntitiesLock);
_recentlyDeletedEntityItemIDs.insert(usecTimestampNow(), existingEntityItemID);
}
{
QWriteLocker locker(&_entityCertificateIDMapLock);
_entityCertificateIDMap.insert(certID, entityItemID);
qCDebug(entities) << "Certificate ID" << certID << "belongs to" << entityItemID;
}
// Start owner verification.
auto nodeList = DependencyManager::get<NodeList>();
@ -2178,7 +2184,3 @@ QStringList EntityTree::getJointNames(const QUuid& entityID) const {
}
return entity->getJointNames();
}
void EntityTree::startDynamicDomainVerification() {
}

View file

@ -187,6 +187,11 @@ public:
return _recentlyDeletedEntityItemIDs;
}
QHash<QString, EntityItemID> getEntityCertificateIDMap() const {
QReadLocker locker(&_entityCertificateIDMapLock);
return _entityCertificateIDMap;
}
void forgetEntitiesDeletedBefore(quint64 sinceTime);
int processEraseMessage(ReceivedMessage& message, const SharedNodePointer& sourceNode);
@ -369,7 +374,6 @@ protected:
QHash<EntityItemID, EntityItemPointer> _entitiesToAdd;
Q_INVOKABLE void startChallengeOwnershipTimer(const EntityItemID& entityItemID);
void startDynamicDomainVerification();
};
#endif // hifi_EntityTree_h

View file

@ -16,6 +16,8 @@
(function () { // BEGIN LOCAL_SCOPE
Script.include("/~/system/libraries/accountUtils.js");
var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace";
// Function Name: onButtonClicked()
//
// Description:
@ -88,6 +90,9 @@
case 'goToPurchases':
tablet.pushOntoStack(MARKETPLACE_PURCHASES_QML_PATH);
break;
case 'goToMarketplaceItemPage':
tablet.gotoWebScreen(MARKETPLACE_URL + '/items/' + message.itemId, MARKETPLACES_INJECT_SCRIPT_URL);
break;
default:
print('Unrecognized message from QML:', JSON.stringify(message));
}

View file

@ -334,7 +334,6 @@
$('body').addClass("code-injected");
maybeAddLogInButton();
maybeAddSetupWalletButton();
changeDropdownMenu();
var purchaseButton = $('#side-info').find('.btn').first();

View file

@ -289,13 +289,19 @@
openWallet();
break;
case 'purchases_walletNotSetUp':
case 'checkout_walletNotSetUp':
wireEventBridge(true);
tablet.sendToQml({
method: 'updateWalletReferrer',
referrer: "purchases"
});
openWallet();
case 'checkout_walletNotSetUp':
wireEventBridge(true);
tablet.sendToQml({
method: 'updateWalletReferrer',
referrer: message.itemId
});
openWallet();
break;
case 'checkout_cancelClicked':
tablet.gotoWebScreen(MARKETPLACE_URL + '/items/' + message.params, MARKETPLACES_INJECT_SCRIPT_URL);