From f997ad4628bf95b18f4ced5390adc23f989cab1b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 7 Nov 2017 16:15:48 -0800 Subject: [PATCH 01/30] changed Wallet from RSA to ECSDA cryto --- interface/src/commerce/Wallet.cpp | 150 ++++++++++++++++-------------- 1 file changed, 79 insertions(+), 71 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 85632ff8f1..8c606f0418 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -32,6 +32,7 @@ #include #include #include +#include // I know, right? But per https://www.openssl.org/docs/faq.html // this avoids OPENSSL_Uplink(00007FF847238000,08): no OPENSSL_Applink @@ -78,18 +79,19 @@ int passwordCallback(char* password, int maxPasswordSize, int rwFlag, void* u) { } } -RSA* readKeys(const char* filename) { +EC_KEY* readKeys(const char* filename) { FILE* fp; - RSA* key = NULL; + EC_KEY *key = NULL; if ((fp = fopen(filename, "rt"))) { // file opened successfully qCDebug(commerce) << "opened key file" << filename; - if ((key = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL))) { + + if ((key = PEM_read_EC_PUBKEY(fp, NULL, NULL, NULL))) { // now read private key qCDebug(commerce) << "read public key"; - if ((key = PEM_read_RSAPrivateKey(fp, &key, passwordCallback, NULL))) { + if ((key = PEM_read_ECPrivateKey(fp, &key, passwordCallback, NULL))) { qCDebug(commerce) << "read private key"; fclose(fp); return key; @@ -137,18 +139,18 @@ bool Wallet::writeBackupInstructions() { return retval; } -bool writeKeys(const char* filename, RSA* keys) { +bool writeKeys(const char* filename, EC_KEY* keys) { FILE* fp; bool retval = false; if ((fp = fopen(filename, "wt"))) { - if (!PEM_write_RSAPublicKey(fp, keys)) { + if (!PEM_write_EC_PUBKEY(fp, keys)) { fclose(fp); qCDebug(commerce) << "failed to write public key"; QFile(QString(filename)).remove(); return retval; } - if (!PEM_write_RSAPrivateKey(fp, keys, EVP_des_ede3_cbc(), NULL, 0, passwordCallback, NULL)) { + if (!PEM_write_ECPrivateKey(fp, keys, EVP_des_ede3_cbc(), NULL, 0, passwordCallback, NULL)) { fclose(fp); qCDebug(commerce) << "failed to write private key"; QFile(QString(filename)).remove(); @@ -170,44 +172,28 @@ bool writeKeys(const char* filename, RSA* keys) { // TODO: we don't really use the private keys returned - we can see how this evolves, but probably // we should just return a list of public keys? // or perhaps return the RSA* instead? -QPair generateRSAKeypair() { - - RSA* keyPair = RSA_new(); - BIGNUM* exponent = BN_new(); +QPair generateECKeypair() { + + EC_KEY* keyPair = EC_KEY_new_by_curve_name(NID_secp256k1); QPair retval; - - const unsigned long RSA_KEY_EXPONENT = 65537; - BN_set_word(exponent, RSA_KEY_EXPONENT); - - // seed the random number generator before we call RSA_generate_key_ex - srand(time(NULL)); - - const int RSA_KEY_BITS = 2048; - - if (!RSA_generate_key_ex(keyPair, RSA_KEY_BITS, exponent, NULL)) { - qCDebug(commerce) << "Error generating 2048-bit RSA Keypair -" << ERR_get_error(); - - // we're going to bust out of here but first we cleanup the BIGNUM - BN_free(exponent); + if (!EC_KEY_generate_key(keyPair)) { + qCDebug(commerce) << "Error generating EC Keypair -" << ERR_get_error(); return retval; } - // we don't need the BIGNUM anymore so clean that up - BN_free(exponent); - // grab the public key and private key from the file unsigned char* publicKeyDER = NULL; - int publicKeyLength = i2d_RSAPublicKey(keyPair, &publicKeyDER); + int publicKeyLength = i2d_EC_PUBKEY(keyPair, &publicKeyDER); unsigned char* privateKeyDER = NULL; - int privateKeyLength = i2d_RSAPrivateKey(keyPair, &privateKeyDER); + int privateKeyLength = i2d_ECPrivateKey(keyPair, &privateKeyDER); if (publicKeyLength <= 0 || privateKeyLength <= 0) { qCDebug(commerce) << "Error getting DER public or private key from RSA struct -" << ERR_get_error(); // cleanup the RSA struct - RSA_free(keyPair); + EC_KEY_free(keyPair); // cleanup the public and private key DER data, if required if (publicKeyLength > 0) { @@ -227,7 +213,7 @@ QPair generateRSAKeypair() { return retval; } - RSA_free(keyPair); + EC_KEY_free(keyPair); // prepare the return values. TODO: Fix this - we probably don't really even want the // private key at all (better to read it when we need it?). Or maybe we do, when we have @@ -245,18 +231,18 @@ QPair generateRSAKeypair() { // the public key can just go into a byte array QByteArray readPublicKey(const char* filename) { FILE* fp; - RSA* key = NULL; + EC_KEY* key = NULL; if ((fp = fopen(filename, "r"))) { // file opened successfully qCDebug(commerce) << "opened key file" << filename; - if ((key = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL))) { + if ((key = PEM_read_EC_PUBKEY(fp, NULL, NULL, NULL))) { // file read successfully unsigned char* publicKeyDER = NULL; - int publicKeyLength = i2d_RSAPublicKey(key, &publicKeyDER); + int publicKeyLength = i2d_EC_PUBKEY(key, &publicKeyDER); // TODO: check for 0 length? // cleanup - RSA_free(key); + EC_KEY_free(key); fclose(fp); qCDebug(commerce) << "parsed public key file successfully"; @@ -274,15 +260,15 @@ QByteArray readPublicKey(const char* filename) { return QByteArray(); } -// the private key should be read/copied into heap memory. For now, we need the RSA struct +// the private key should be read/copied into heap memory. For now, we need the EC_KEY struct // so I'll return that. Note we need to RSA_free(key) later!!! -RSA* readPrivateKey(const char* filename) { +EC_KEY* readPrivateKey(const char* filename) { FILE* fp; - RSA* key = NULL; + EC_KEY* key = NULL; if ((fp = fopen(filename, "r"))) { // file opened successfully qCDebug(commerce) << "opened key file" << filename; - if ((key = PEM_read_RSAPrivateKey(fp, &key, passwordCallback, NULL))) { + if ((key = PEM_read_ECPrivateKey(fp, &key, passwordCallback, NULL))) { qCDebug(commerce) << "parsed private key file successfully"; } else { @@ -509,7 +495,7 @@ bool Wallet::walletIsAuthenticatedWithPassphrase() { if (publicKey.size() > 0) { if (auto key = readPrivateKey(keyFilePath().toStdString().c_str())) { - RSA_free(key); + EC_KEY_free(key); // be sure to add the public key so we don't do this over and over _publicKeys.push_back(publicKey.toBase64()); @@ -525,7 +511,7 @@ bool Wallet::generateKeyPair() { initialize(); qCInfo(commerce) << "Generating keypair."; - auto keyPair = generateRSAKeypair(); + auto keyPair = generateECKeypair(); writeBackupInstructions(); @@ -558,22 +544,30 @@ QStringList Wallet::listPublicKeys() { // encoded string representing the signature (suitable for http, etc...) QString Wallet::signWithKey(const QByteArray& text, const QString& key) { qCInfo(commerce) << "Signing text."; - RSA* rsaPrivateKey = NULL; - if ((rsaPrivateKey = readPrivateKey(keyFilePath().toStdString().c_str()))) { - QByteArray signature(RSA_size(rsaPrivateKey), 0); + EC_KEY* ecPrivateKey = NULL; + if ((ecPrivateKey = readPrivateKey(keyFilePath().toStdString().c_str()))) { + QByteArray signature(ECDSA_size(ecPrivateKey), 0); unsigned int signatureBytes = 0; QByteArray hashedPlaintext = QCryptographicHash::hash(text, QCryptographicHash::Sha256); - int encryptReturn = RSA_sign(NID_sha256, - reinterpret_cast(hashedPlaintext.constData()), - hashedPlaintext.size(), - reinterpret_cast(signature.data()), - &signatureBytes, - rsaPrivateKey); + + int encryptReturn = ECDSA_sign(0, + reinterpret_cast(hashedPlaintext.constData()), + hashedPlaintext.size(), + reinterpret_cast(signature.data()), + &signatureBytes, ecPrivateKey); + + //Previous pattern, retained by ECDSA_sign + //int encryptReturn = RSA_sign(NID_sha256, + // reinterpret_cast(hashedPlaintext.constData()), + // hashedPlaintext.size(), + // reinterpret_cast(signature.data()), + // &signatureBytes, + // rsaPrivateKey); // free the private key RSA struct now that we are done with it - RSA_free(rsaPrivateKey); + EC_KEY_free(ecPrivateKey); if (encryptReturn != -1) { return signature.toBase64(); @@ -674,7 +668,7 @@ void Wallet::reset() { keyFile.remove(); } bool Wallet::writeWallet(const QString& newPassphrase) { - RSA* keys = readKeys(keyFilePath().toStdString().c_str()); + EC_KEY* keys = readKeys(keyFilePath().toStdString().c_str()); if (keys) { // we read successfully, so now write to a new temp file QString tempFileName = QString("%1.%2").arg(keyFilePath(), QString("temp")); @@ -720,18 +714,23 @@ bool Wallet::changePassphrase(const QString& newPassphrase) { void Wallet::handleChallengeOwnershipPacket(QSharedPointer packet, SharedNodePointer sendingNode) { auto nodeList = DependencyManager::get(); + //With EC keys, we receive a nonce from the metaverse server, which is signed + //here with the private key and returned. Verification is done at server. + bool challengeOriginatedFromClient = packet->getType() == PacketType::ChallengeOwnershipRequest; - unsigned char decryptedText[64]; + //unsigned char decryptedText[64]; + int decryptionStatus; int certIDByteArraySize; int encryptedTextByteArraySize; int challengingNodeUUIDByteArraySize; packet->readPrimitive(&certIDByteArraySize); - packet->readPrimitive(&encryptedTextByteArraySize); + packet->readPrimitive(&encryptedTextByteArraySize); //rerturns a cast char*, size if (challengeOriginatedFromClient) { packet->readPrimitive(&challengingNodeUUIDByteArraySize); } + //"encryptedText" is now a series of random bytes, a nonce QByteArray certID = packet->read(certIDByteArraySize); QByteArray encryptedText = packet->read(encryptedTextByteArraySize); QByteArray challengingNodeUUID; @@ -739,25 +738,34 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack challengingNodeUUID = packet->read(challengingNodeUUIDByteArraySize); } - RSA* rsa = readKeys(keyFilePath().toStdString().c_str()); - int decryptionStatus = -1; + EC_KEY* ec = readKeys(keyFilePath().toStdString().c_str()); + QString sig; + // int decryptionStatus = -1; - if (rsa) { + if (ec) { ERR_clear_error(); - decryptionStatus = RSA_private_decrypt(encryptedTextByteArraySize, - reinterpret_cast(encryptedText.constData()), - decryptedText, - rsa, - RSA_PKCS1_OAEP_PADDING); + sig = signWithKey(encryptedText, ""); //base64 signature, QByteArray cast + //upon return to QString - RSA_free(rsa); + // decryptionStatus = RSA_private_decrypt(encryptedTextByteArraySize, + // reinterpret_cast(encryptedText.constData()), + // decryptedText, //unsigned char* + // ec, + // RSA_PKCS1_OAEP_PADDING); + + EC_KEY_free(ec); + decryptionStatus = 1; } else { - qCDebug(commerce) << "During entity ownership challenge, creating the RSA object failed."; + qCDebug(commerce) << "During entity ownership challenge, creating the EC-signed nonce failed."; + decryptionStatus = -1; } + QByteArray ba = sig.toLocal8Bit(); + const char *sigChar = ba.data(); + QByteArray decryptedTextByteArray; if (decryptionStatus > -1) { - decryptedTextByteArray = QByteArray(reinterpret_cast(decryptedText), decryptionStatus); + decryptedTextByteArray = QByteArray(sigChar, decryptionStatus); } int decryptedTextByteArraySize = decryptedTextByteArray.size(); int certIDSize = certID.size(); @@ -774,7 +782,7 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack decryptedTextPacket->write(decryptedTextByteArray); decryptedTextPacket->write(challengingNodeUUID); - qCDebug(commerce) << "Sending ChallengeOwnershipReply Packet containing decrypted text" << decryptedTextByteArray << "for CertID" << certID; + qCDebug(commerce) << "Sending ChallengeOwnershipReply Packet containing signed text" << decryptedTextByteArray << "for CertID" << certID; nodeList->sendPacket(std::move(decryptedTextPacket), *sendingNode); } else { @@ -785,17 +793,17 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack decryptedTextPacket->write(certID); decryptedTextPacket->write(decryptedTextByteArray); - qCDebug(commerce) << "Sending ChallengeOwnership Packet containing decrypted text" << decryptedTextByteArray << "for CertID" << certID; + qCDebug(commerce) << "Sending ChallengeOwnership Packet containing signed text" << decryptedTextByteArray << "for CertID" << certID; nodeList->sendPacket(std::move(decryptedTextPacket), *sendingNode); } if (decryptionStatus == -1) { - qCDebug(commerce) << "During entity ownership challenge, decrypting the encrypted text failed."; + qCDebug(commerce) << "During entity ownership challenge, signing the text failed."; long error = ERR_get_error(); if (error != 0) { const char* error_str = ERR_error_string(error, NULL); - qCWarning(entities) << "RSA error:" << error_str; + qCWarning(entities) << "EC error:" << error_str; } } } @@ -818,4 +826,4 @@ void Wallet::getWalletStatus() { walletScriptingInterface->setWalletStatus(status); return; } -} +} \ No newline at end of file From 44f2c92d30dae2d30626efcc03bd49703466c9d8 Mon Sep 17 00:00:00 2001 From: H Q Date: Tue, 14 Nov 2017 15:40:29 -0800 Subject: [PATCH 02/30] Final ECSDA and nonce modifications for this dev cycle --- interface/src/commerce/Wallet.cpp | 71 ++++++------ .../ui/overlays/ContextOverlayInterface.cpp | 18 +-- .../entities/src/EntityItemProperties.cpp | 23 ++-- libraries/entities/src/EntityTree.cpp | 104 +++++++++--------- libraries/entities/src/EntityTree.h | 6 +- 5 files changed, 113 insertions(+), 109 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 8c606f0418..59b2f03ed8 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -27,7 +27,6 @@ #include #include -#include #include #include #include @@ -552,7 +551,7 @@ QString Wallet::signWithKey(const QByteArray& text, const QString& key) { QByteArray hashedPlaintext = QCryptographicHash::hash(text, QCryptographicHash::Sha256); - int encryptReturn = ECDSA_sign(0, + int Return = ECDSA_sign(0, reinterpret_cast(hashedPlaintext.constData()), hashedPlaintext.size(), reinterpret_cast(signature.data()), @@ -569,7 +568,7 @@ QString Wallet::signWithKey(const QByteArray& text, const QString& key) { // free the private key RSA struct now that we are done with it EC_KEY_free(ecPrivateKey); - if (encryptReturn != -1) { + if (Return != -1) { return signature.toBase64(); } } @@ -719,20 +718,20 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack bool challengeOriginatedFromClient = packet->getType() == PacketType::ChallengeOwnershipRequest; //unsigned char decryptedText[64]; - int decryptionStatus; + int Status; int certIDByteArraySize; - int encryptedTextByteArraySize; + int TextByteArraySize; int challengingNodeUUIDByteArraySize; packet->readPrimitive(&certIDByteArraySize); - packet->readPrimitive(&encryptedTextByteArraySize); //rerturns a cast char*, size + packet->readPrimitive(&TextByteArraySize); //rerturns a cast char*, size if (challengeOriginatedFromClient) { packet->readPrimitive(&challengingNodeUUIDByteArraySize); } //"encryptedText" is now a series of random bytes, a nonce QByteArray certID = packet->read(certIDByteArraySize); - QByteArray encryptedText = packet->read(encryptedTextByteArraySize); + QByteArray Text = packet->read(TextByteArraySize); QByteArray challengingNodeUUID; if (challengeOriginatedFromClient) { challengingNodeUUID = packet->read(challengingNodeUUIDByteArraySize); @@ -742,10 +741,10 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack QString sig; // int decryptionStatus = -1; - if (ec) { + if (ec) { ERR_clear_error(); - sig = signWithKey(encryptedText, ""); //base64 signature, QByteArray cast - //upon return to QString + sig = signWithKey(Text, ""); //base64 signature, QByteArray cast + //upon return to QString // decryptionStatus = RSA_private_decrypt(encryptedTextByteArraySize, // reinterpret_cast(encryptedText.constData()), @@ -753,52 +752,52 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack // ec, // RSA_PKCS1_OAEP_PADDING); - EC_KEY_free(ec); - decryptionStatus = 1; + // EC_KEY_free(ec); + Status = 1; } else { qCDebug(commerce) << "During entity ownership challenge, creating the EC-signed nonce failed."; - decryptionStatus = -1; + Status = -1; } QByteArray ba = sig.toLocal8Bit(); const char *sigChar = ba.data(); - QByteArray decryptedTextByteArray; - if (decryptionStatus > -1) { - decryptedTextByteArray = QByteArray(sigChar, decryptionStatus); - } - int decryptedTextByteArraySize = decryptedTextByteArray.size(); + QByteArray TextByteArray; + // if (decryptionStatus > -1) { + TextByteArray = QByteArray(sigChar, Status); + //} + TextByteArraySize = TextByteArray.size(); int certIDSize = certID.size(); // setup the packet if (challengeOriginatedFromClient) { - auto decryptedTextPacket = NLPacket::create(PacketType::ChallengeOwnershipReply, - certIDSize + decryptedTextByteArraySize + challengingNodeUUIDByteArraySize + 3 * sizeof(int), + auto TextPacket = NLPacket::create(PacketType::ChallengeOwnershipReply, + certIDSize + TextByteArraySize + challengingNodeUUIDByteArraySize + 3 * sizeof(int), true); - decryptedTextPacket->writePrimitive(certIDSize); - decryptedTextPacket->writePrimitive(decryptedTextByteArraySize); - decryptedTextPacket->writePrimitive(challengingNodeUUIDByteArraySize); - decryptedTextPacket->write(certID); - decryptedTextPacket->write(decryptedTextByteArray); - decryptedTextPacket->write(challengingNodeUUID); + TextPacket->writePrimitive(certIDSize); + TextPacket->writePrimitive(TextByteArraySize); + TextPacket->writePrimitive(challengingNodeUUIDByteArraySize); + TextPacket->write(certID); + TextPacket->write(TextByteArray); + TextPacket->write(challengingNodeUUID); - qCDebug(commerce) << "Sending ChallengeOwnershipReply Packet containing signed text" << decryptedTextByteArray << "for CertID" << certID; + qCDebug(commerce) << "Sending ChallengeOwnershipReply Packet containing signed text" << TextByteArray << "for CertID" << certID; - nodeList->sendPacket(std::move(decryptedTextPacket), *sendingNode); + nodeList->sendPacket(std::move(TextPacket), *sendingNode); } else { - auto decryptedTextPacket = NLPacket::create(PacketType::ChallengeOwnership, certIDSize + decryptedTextByteArraySize + 2 * sizeof(int), true); + auto TextPacket = NLPacket::create(PacketType::ChallengeOwnership, certIDSize + TextByteArraySize + 2 * sizeof(int), true); - decryptedTextPacket->writePrimitive(certIDSize); - decryptedTextPacket->writePrimitive(decryptedTextByteArraySize); - decryptedTextPacket->write(certID); - decryptedTextPacket->write(decryptedTextByteArray); + TextPacket->writePrimitive(certIDSize); + TextPacket->writePrimitive(TextByteArraySize); + TextPacket->write(certID); + TextPacket->write(TextByteArray); - qCDebug(commerce) << "Sending ChallengeOwnership Packet containing signed text" << decryptedTextByteArray << "for CertID" << certID; + qCDebug(commerce) << "Sending ChallengeOwnership Packet containing signed text" << TextByteArray << "for CertID" << certID; - nodeList->sendPacket(std::move(decryptedTextPacket), *sendingNode); + nodeList->sendPacket(std::move(TextPacket), *sendingNode); } - if (decryptionStatus == -1) { + if (Status == -1) { qCDebug(commerce) << "During entity ownership challenge, signing the text failed."; long error = ERR_get_error(); if (error != 0) { diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index b5af529f2b..dee8eaad0b 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -311,21 +311,21 @@ void ContextOverlayInterface::openInspectionCertificate() { QString ownerKey = jsonObject["transfer_recipient_key"].toString(); QByteArray certID = entityProperties.getCertificateID().toUtf8(); - QByteArray encryptedText = DependencyManager::get()->getTree()->computeEncryptedNonce(certID, ownerKey); + QByteArray Text = DependencyManager::get()->getTree()->computeNonce(certID, ownerKey); QByteArray nodeToChallengeByteArray = entityProperties.getOwningAvatarID().toRfc4122(); int certIDByteArraySize = certID.length(); - int encryptedTextByteArraySize = encryptedText.length(); + int TextByteArraySize = Text.length(); int nodeToChallengeByteArraySize = nodeToChallengeByteArray.length(); auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest, - certIDByteArraySize + encryptedTextByteArraySize + nodeToChallengeByteArraySize + 3 * sizeof(int), + certIDByteArraySize + TextByteArraySize + nodeToChallengeByteArraySize + 3 * sizeof(int), true); challengeOwnershipPacket->writePrimitive(certIDByteArraySize); - challengeOwnershipPacket->writePrimitive(encryptedTextByteArraySize); + challengeOwnershipPacket->writePrimitive(TextByteArraySize); challengeOwnershipPacket->writePrimitive(nodeToChallengeByteArraySize); challengeOwnershipPacket->write(certID); - challengeOwnershipPacket->write(encryptedText); + challengeOwnershipPacket->write(Text); challengeOwnershipPacket->write(nodeToChallengeByteArray); nodeList->sendPacket(std::move(challengeOwnershipPacket), *entityServer); @@ -406,16 +406,16 @@ void ContextOverlayInterface::handleChallengeOwnershipReplyPacket(QSharedPointer _challengeOwnershipTimeoutTimer.stop(); int certIDByteArraySize; - int decryptedTextByteArraySize; + int TextByteArraySize; packet->readPrimitive(&certIDByteArraySize); - packet->readPrimitive(&decryptedTextByteArraySize); + packet->readPrimitive(&TextByteArraySize); QString certID(packet->read(certIDByteArraySize)); - QString decryptedText(packet->read(decryptedTextByteArraySize)); + QString Text(packet->read(TextByteArraySize)); EntityItemID id; - bool verificationSuccess = DependencyManager::get()->getTree()->verifyDecryptedNonce(certID, decryptedText, id); + bool verificationSuccess = DependencyManager::get()->getTree()->verifyNonce(certID, Text, id); if (verificationSuccess) { emit ledger->updateCertificateStatus(certID, (uint)(ledger->CERTIFICATE_STATUS_VERIFICATION_SUCCESS)); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index f774b208c4..9435e456a2 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -15,14 +15,14 @@ #include #include -#include + #include #include #include #include #include #include - +#include #include #include #include @@ -2531,8 +2531,8 @@ bool EntityItemProperties::verifyStaticCertificateProperties() { BIO *bio = BIO_new_mem_buf((void*)marketplacePublicKey, marketplacePublicKeyLength); EVP_PKEY* evp_key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); if (evp_key) { - RSA* rsa = EVP_PKEY_get1_RSA(evp_key); - if (rsa) { + EC_KEY* ec = EVP_PKEY_get1_EC_KEY(evp_key); + if (ec) { const QByteArray digestByteArray = getStaticCertificateHash(); const unsigned char* digest = reinterpret_cast(digestByteArray.constData()); int digestLength = digestByteArray.length(); @@ -2542,22 +2542,25 @@ bool EntityItemProperties::verifyStaticCertificateProperties() { int signatureLength = signatureByteArray.length(); ERR_clear_error(); - bool answer = RSA_verify(NID_sha256, + //ECSDA verification prototype: note that type is currently ignored + //int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen, + // const unsigned char *sig, int siglen, EC_KEY *eckey); + bool answer = ECDSA_verify(0, digest, digestLength, signature, signatureLength, - rsa); + ec); long error = ERR_get_error(); if (error != 0) { const char* error_str = ERR_error_string(error, NULL); - qCWarning(entities) << "ERROR while verifying static certificate properties! RSA error:" << error_str + qCWarning(entities) << "ERROR while verifying static certificate properties! EC error:" << error_str << "\nStatic Cert JSON:" << getStaticCertificateJSON() << "\nKey:" << EntityItem::_marketplacePublicKey << "\nKey Length:" << marketplacePublicKeyLength << "\nDigest:" << digest << "\nDigest Length:" << digestLength << "\nSignature:" << signature << "\nSignature Length:" << signatureLength; } - RSA_free(rsa); + EC_KEY_free(ec); if (bio) { BIO_free(bio); } @@ -2574,7 +2577,7 @@ bool EntityItemProperties::verifyStaticCertificateProperties() { } long error = ERR_get_error(); const char* error_str = ERR_error_string(error, NULL); - qCWarning(entities) << "Failed to verify static certificate properties! RSA error:" << error_str; + qCWarning(entities) << "Failed to verify static certificate properties! EC error:" << error_str; return false; } } else { @@ -2583,7 +2586,7 @@ bool EntityItemProperties::verifyStaticCertificateProperties() { } long error = ERR_get_error(); const char* error_str = ERR_error_string(error, NULL); - qCWarning(entities) << "Failed to verify static certificate properties! RSA error:" << error_str; + qCWarning(entities) << "Failed to verify static certificate properties! EC error:" << error_str; return false; } } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 333a514377..d2be600022 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -14,7 +14,7 @@ #include #include -#include +//#include #include #include #include @@ -1167,36 +1167,38 @@ void EntityTree::startPendingTransferStatusTimer(const QString& certID, const En transferStatusRetryTimer->start(90000); } -QByteArray EntityTree::computeEncryptedNonce(const QString& certID, const QString ownerKey) { - QString ownerKeyWithHeaders = ("-----BEGIN RSA PUBLIC KEY-----\n" + ownerKey + "\n-----END RSA PUBLIC KEY-----"); +QByteArray EntityTree::computeNonce(const QString& certID, const QString ownerKey) { + QString ownerKeyWithHeaders = ("-----BEGIN ECDSA PUBLIC KEY-----\n" + ownerKey + "\n-----END ECDSA PUBLIC KEY-----"); BIO* bio = BIO_new_mem_buf((void*)ownerKeyWithHeaders.toUtf8().constData(), -1); BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); // NO NEWLINE - RSA* rsa = PEM_read_bio_RSAPublicKey(bio, NULL, NULL, NULL); + EC_KEY* ec = PEM_read_bio_EC_PUBKEY(bio, NULL, NULL, NULL); - if (rsa) { - QUuid nonce = QUuid::createUuid(); - const unsigned int textLength = nonce.toString().length(); - QByteArray encryptedText(RSA_size(rsa), 0); - const int encryptStatus = RSA_public_encrypt(textLength, - reinterpret_cast(qPrintable(nonce.toString())), - reinterpret_cast(encryptedText.data()), - rsa, - RSA_PKCS1_OAEP_PADDING); + if (ec) { + QUuid nonce = QUuid::createUuid(); //random, 5-hex value, separated by "-" + QByteArray nonceBytes = nonce.toByteArray(); + + //const unsigned int textLength = nonce.toString().length(); + //QByteArray encryptedText(ECDSA_size(ec), 0); + //const int encryptStatus = RSA_public_encrypt(textLength, + // reinterpret_cast(qPrintable(nonce.toString())), + // reinterpret_cast(encryptedText.data()), + // rsa, + // RSA_PKCS1_OAEP_PADDING); if (bio) { BIO_free(bio); } - RSA_free(rsa); - if (encryptStatus == -1) { - long error = ERR_get_error(); - const char* error_str = ERR_error_string(error, NULL); - qCWarning(entities) << "Unable to compute encrypted nonce for" << certID << "\nRSA error:" << error_str; - return ""; - } + //rsa_free(ec); + // if (encryptStatus == -1) { + // long error = ERR_get_error(); + // const char* error_str = ERR_error_string(error, NULL); + // qCWarning(entities) << "Unable to compute nonce for" << certID << "\nECDSA error:" << error_str; + // return ""; + //} QWriteLocker locker(&_certNonceMapLock); _certNonceMap.insert(certID, nonce); - return encryptedText; + return nonceBytes; } else { if (bio) { BIO_free(bio); @@ -1205,7 +1207,7 @@ QByteArray EntityTree::computeEncryptedNonce(const QString& certID, const QStrin } } -bool EntityTree::verifyDecryptedNonce(const QString& certID, const QString& decryptedNonce, EntityItemID& id) { +bool EntityTree::verifyNonce(const QString& certID, const QString& Nonce, EntityItemID& id) { { QReadLocker certIdMapLocker(&_entityCertificateIDMapLock); id = _entityCertificateIDMap.value(certID); @@ -1217,13 +1219,13 @@ bool EntityTree::verifyDecryptedNonce(const QString& certID, const QString& decr actualNonce = _certNonceMap.take(certID).toString(); } - bool verificationSuccess = (actualNonce == decryptedNonce); + bool verificationSuccess = (actualNonce == Nonce); if (verificationSuccess) { qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "succeeded."; } else { qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "failed." - << "\nActual nonce:" << actualNonce << "\nDecrypted nonce:" << decryptedNonce; + << "\nActual nonce:" << actualNonce << "\nonce:" << Nonce; } return verificationSuccess; @@ -1231,67 +1233,67 @@ bool EntityTree::verifyDecryptedNonce(const QString& certID, const QString& decr void EntityTree::processChallengeOwnershipRequestPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { int certIDByteArraySize; - int encryptedTextByteArraySize; + int TextByteArraySize; int nodeToChallengeByteArraySize; message.readPrimitive(&certIDByteArraySize); - message.readPrimitive(&encryptedTextByteArraySize); + message.readPrimitive(&TextByteArraySize); message.readPrimitive(&nodeToChallengeByteArraySize); QByteArray certID(message.read(certIDByteArraySize)); - QByteArray encryptedText(message.read(encryptedTextByteArraySize)); + QByteArray Text(message.read(TextByteArraySize)); QByteArray nodeToChallenge(message.read(nodeToChallengeByteArraySize)); - sendChallengeOwnershipRequestPacket(certID, encryptedText, nodeToChallenge, sourceNode); + sendChallengeOwnershipRequestPacket(certID, Text, nodeToChallenge, sourceNode); } void EntityTree::processChallengeOwnershipReplyPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { auto nodeList = DependencyManager::get(); int certIDByteArraySize; - int decryptedTextByteArraySize; + int TextByteArraySize; int challengingNodeUUIDByteArraySize; message.readPrimitive(&certIDByteArraySize); - message.readPrimitive(&decryptedTextByteArraySize); + message.readPrimitive(&TextByteArraySize); message.readPrimitive(&challengingNodeUUIDByteArraySize); QByteArray certID(message.read(certIDByteArraySize)); - QByteArray decryptedText(message.read(decryptedTextByteArraySize)); + QByteArray Text(message.read(TextByteArraySize)); QUuid challengingNode = QUuid::fromRfc4122(message.read(challengingNodeUUIDByteArraySize)); auto challengeOwnershipReplyPacket = NLPacket::create(PacketType::ChallengeOwnershipReply, - certIDByteArraySize + decryptedText.length() + 2 * sizeof(int), + certIDByteArraySize + Text.length() + 2 * sizeof(int), true); challengeOwnershipReplyPacket->writePrimitive(certIDByteArraySize); - challengeOwnershipReplyPacket->writePrimitive(decryptedText.length()); + challengeOwnershipReplyPacket->writePrimitive(Text.length()); challengeOwnershipReplyPacket->write(certID); - challengeOwnershipReplyPacket->write(decryptedText); + challengeOwnershipReplyPacket->write(Text); nodeList->sendPacket(std::move(challengeOwnershipReplyPacket), *(nodeList->nodeWithUUID(challengingNode))); } void EntityTree::sendChallengeOwnershipPacket(const QString& certID, const QString& ownerKey, const EntityItemID& entityItemID, const SharedNodePointer& senderNode) { - // 1. Encrypt a nonce with the owner's public key + // 1. Obtain a nonce auto nodeList = DependencyManager::get(); - QByteArray encryptedText = computeEncryptedNonce(certID, ownerKey); + QByteArray Text = computeNonce(certID, ownerKey); - if (encryptedText == "") { - qCDebug(entities) << "CRITICAL ERROR: Couldn't compute encrypted nonce. Deleting entity..."; + if (Text == "") { + qCDebug(entities) << "CRITICAL ERROR: Couldn't compute nonce. Deleting entity..."; deleteEntity(entityItemID, true); } else { qCDebug(entities) << "Challenging ownership of Cert ID" << certID; - // 2. Send the encrypted text to the rezzing avatar's node + // 2. Send the nonce to the rezzing avatar's node QByteArray certIDByteArray = certID.toUtf8(); int certIDByteArraySize = certIDByteArray.size(); auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnership, - certIDByteArraySize + encryptedText.length() + 2 * sizeof(int), + certIDByteArraySize + Text.length() + 2 * sizeof(int), true); challengeOwnershipPacket->writePrimitive(certIDByteArraySize); - challengeOwnershipPacket->writePrimitive(encryptedText.length()); + challengeOwnershipPacket->writePrimitive(Text.length()); challengeOwnershipPacket->write(certIDByteArray); - challengeOwnershipPacket->write(encryptedText); + challengeOwnershipPacket->write(Text); nodeList->sendPacket(std::move(challengeOwnershipPacket), *senderNode); // 3. Kickoff a 10-second timeout timer that deletes the entity if we don't get an ownership response in time @@ -1304,7 +1306,7 @@ void EntityTree::sendChallengeOwnershipPacket(const QString& certID, const QStri } } -void EntityTree::sendChallengeOwnershipRequestPacket(const QByteArray& certID, const QByteArray& encryptedText, const QByteArray& nodeToChallenge, const SharedNodePointer& senderNode) { +void EntityTree::sendChallengeOwnershipRequestPacket(const QByteArray& certID, const QByteArray& Text, const QByteArray& nodeToChallenge, const SharedNodePointer& senderNode) { auto nodeList = DependencyManager::get(); // In this case, Client A is challenging Client B. Client A is inspecting a certified entity that it wants @@ -1312,17 +1314,17 @@ void EntityTree::sendChallengeOwnershipRequestPacket(const QByteArray& certID, c QByteArray senderNodeUUID = senderNode->getUUID().toRfc4122(); int certIDByteArraySize = certID.length(); - int encryptedTextByteArraySize = encryptedText.length(); + int TextByteArraySize = Text.length(); int senderNodeUUIDSize = senderNodeUUID.length(); auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest, - certIDByteArraySize + encryptedTextByteArraySize + senderNodeUUIDSize + 3 * sizeof(int), + certIDByteArraySize + TextByteArraySize + senderNodeUUIDSize + 3 * sizeof(int), true); challengeOwnershipPacket->writePrimitive(certIDByteArraySize); - challengeOwnershipPacket->writePrimitive(encryptedTextByteArraySize); + challengeOwnershipPacket->writePrimitive(TextByteArraySize); challengeOwnershipPacket->writePrimitive(senderNodeUUIDSize); challengeOwnershipPacket->write(certID); - challengeOwnershipPacket->write(encryptedText); + challengeOwnershipPacket->write(Text); challengeOwnershipPacket->write(senderNodeUUID); nodeList->sendPacket(std::move(challengeOwnershipPacket), *(nodeList->nodeWithUUID(QUuid::fromRfc4122(nodeToChallenge)))); @@ -1391,18 +1393,18 @@ void EntityTree::validatePop(const QString& certID, const EntityItemID& entityIt void EntityTree::processChallengeOwnershipPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { int certIDByteArraySize; - int decryptedTextByteArraySize; + int TextByteArraySize; message.readPrimitive(&certIDByteArraySize); - message.readPrimitive(&decryptedTextByteArraySize); + message.readPrimitive(&TextByteArraySize); QString certID(message.read(certIDByteArraySize)); - QString decryptedText(message.read(decryptedTextByteArraySize)); + QString Text(message.read(TextByteArraySize)); emit killChallengeOwnershipTimeoutTimer(certID); EntityItemID id; - if (!verifyDecryptedNonce(certID, decryptedText, id)) { + if (!verifyNonce(certID, Text, id)) { if (!id.isNull()) { deleteEntity(id, true); } diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 86bfe984f6..fc89a2f65f 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -275,8 +275,8 @@ public: static const float DEFAULT_MAX_TMP_ENTITY_LIFETIME; - QByteArray computeEncryptedNonce(const QString& certID, const QString ownerKey); - bool verifyDecryptedNonce(const QString& certID, const QString& decryptedNonce, EntityItemID& id); + QByteArray computeNonce(const QString& certID, const QString ownerKey); + bool verifyNonce(const QString& certID, const QString& Nonce, EntityItemID& id); signals: void deletingEntity(const EntityItemID& entityID); @@ -381,7 +381,7 @@ protected: private: void sendChallengeOwnershipPacket(const QString& certID, const QString& ownerKey, const EntityItemID& entityItemID, const SharedNodePointer& senderNode); - void sendChallengeOwnershipRequestPacket(const QByteArray& certID, const QByteArray& encryptedText, const QByteArray& nodeToChallenge, const SharedNodePointer& senderNode); + void sendChallengeOwnershipRequestPacket(const QByteArray& certID, const QByteArray& Text, const QByteArray& nodeToChallenge, const SharedNodePointer& senderNode); void validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation); }; From 27350ddbfc846878653d5292a53b8dc820314bb4 Mon Sep 17 00:00:00 2001 From: H Q Date: Thu, 16 Nov 2017 12:35:00 -0800 Subject: [PATCH 03/30] Coding style corrections --- interface/src/commerce/Wallet.cpp | 5 +++-- libraries/entities/src/EntityTree.cpp | 22 +++++++++++----------- libraries/entities/src/EntityTree.h | 4 ++-- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 59b2f03ed8..03cb9ff893 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -175,6 +175,7 @@ QPair generateECKeypair() { EC_KEY* keyPair = EC_KEY_new_by_curve_name(NID_secp256k1); QPair retval; + EC_KEY_set_asn1_flag(keyPair, OPENSSL_EC_NAMED_CURVE); if (!EC_KEY_generate_key(keyPair)) { qCDebug(commerce) << "Error generating EC Keypair -" << ERR_get_error(); return retval; @@ -188,10 +189,10 @@ QPair generateECKeypair() { int privateKeyLength = i2d_ECPrivateKey(keyPair, &privateKeyDER); if (publicKeyLength <= 0 || privateKeyLength <= 0) { - qCDebug(commerce) << "Error getting DER public or private key from RSA struct -" << ERR_get_error(); + qCDebug(commerce) << "Error getting DER public or private key from EC struct -" << ERR_get_error(); - // cleanup the RSA struct + // cleanup the EC struct EC_KEY_free(keyPair); // cleanup the public and private key DER data, if required diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index d2be600022..a5027e68a4 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1233,18 +1233,18 @@ bool EntityTree::verifyNonce(const QString& certID, const QString& Nonce, Entity void EntityTree::processChallengeOwnershipRequestPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { int certIDByteArraySize; - int TextByteArraySize; + int textByteArraySize; int nodeToChallengeByteArraySize; message.readPrimitive(&certIDByteArraySize); - message.readPrimitive(&TextByteArraySize); + message.readPrimitive(&textByteArraySize); message.readPrimitive(&nodeToChallengeByteArraySize); QByteArray certID(message.read(certIDByteArraySize)); - QByteArray Text(message.read(TextByteArraySize)); + QByteArray text(message.read(textByteArraySize)); QByteArray nodeToChallenge(message.read(nodeToChallengeByteArraySize)); - sendChallengeOwnershipRequestPacket(certID, Text, nodeToChallenge, sourceNode); + sendChallengeOwnershipRequestPacket(certID, text, nodeToChallenge, sourceNode); } void EntityTree::processChallengeOwnershipReplyPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { @@ -1306,7 +1306,7 @@ void EntityTree::sendChallengeOwnershipPacket(const QString& certID, const QStri } } -void EntityTree::sendChallengeOwnershipRequestPacket(const QByteArray& certID, const QByteArray& Text, const QByteArray& nodeToChallenge, const SharedNodePointer& senderNode) { +void EntityTree::sendChallengeOwnershipRequestPacket(const QByteArray& certID, const QByteArray& text, const QByteArray& nodeToChallenge, const SharedNodePointer& senderNode) { auto nodeList = DependencyManager::get(); // In this case, Client A is challenging Client B. Client A is inspecting a certified entity that it wants @@ -1314,7 +1314,7 @@ void EntityTree::sendChallengeOwnershipRequestPacket(const QByteArray& certID, c QByteArray senderNodeUUID = senderNode->getUUID().toRfc4122(); int certIDByteArraySize = certID.length(); - int TextByteArraySize = Text.length(); + int TextByteArraySize = text.length(); int senderNodeUUIDSize = senderNodeUUID.length(); auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest, @@ -1324,7 +1324,7 @@ void EntityTree::sendChallengeOwnershipRequestPacket(const QByteArray& certID, c challengeOwnershipPacket->writePrimitive(TextByteArraySize); challengeOwnershipPacket->writePrimitive(senderNodeUUIDSize); challengeOwnershipPacket->write(certID); - challengeOwnershipPacket->write(Text); + challengeOwnershipPacket->write(text); challengeOwnershipPacket->write(senderNodeUUID); nodeList->sendPacket(std::move(challengeOwnershipPacket), *(nodeList->nodeWithUUID(QUuid::fromRfc4122(nodeToChallenge)))); @@ -1393,18 +1393,18 @@ void EntityTree::validatePop(const QString& certID, const EntityItemID& entityIt void EntityTree::processChallengeOwnershipPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { int certIDByteArraySize; - int TextByteArraySize; + int textByteArraySize; message.readPrimitive(&certIDByteArraySize); - message.readPrimitive(&TextByteArraySize); + message.readPrimitive(&textByteArraySize); QString certID(message.read(certIDByteArraySize)); - QString Text(message.read(TextByteArraySize)); + QString text(message.read(textByteArraySize)); emit killChallengeOwnershipTimeoutTimer(certID); EntityItemID id; - if (!verifyNonce(certID, Text, id)) { + if (!verifyNonce(certID, text, id)) { if (!id.isNull()) { deleteEntity(id, true); } diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index fc89a2f65f..b516536e01 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -276,7 +276,7 @@ public: static const float DEFAULT_MAX_TMP_ENTITY_LIFETIME; QByteArray computeNonce(const QString& certID, const QString ownerKey); - bool verifyNonce(const QString& certID, const QString& Nonce, EntityItemID& id); + bool verifyNonce(const QString& certID, const QString& nonce, EntityItemID& id); signals: void deletingEntity(const EntityItemID& entityID); @@ -381,7 +381,7 @@ protected: private: void sendChallengeOwnershipPacket(const QString& certID, const QString& ownerKey, const EntityItemID& entityItemID, const SharedNodePointer& senderNode); - void sendChallengeOwnershipRequestPacket(const QByteArray& certID, const QByteArray& Text, const QByteArray& nodeToChallenge, const SharedNodePointer& senderNode); + void sendChallengeOwnershipRequestPacket(const QByteArray& certID, const QByteArray& text, const QByteArray& nodeToChallenge, const SharedNodePointer& senderNode); void validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation); }; From 21a28827c90840420af310640e701fa2abc582b7 Mon Sep 17 00:00:00 2001 From: H Q Date: Fri, 17 Nov 2017 07:59:52 -0800 Subject: [PATCH 04/30] Remaining coding style changes, other small fixes --- interface/src/commerce/Wallet.cpp | 101 +++++++----------- .../ui/overlays/ContextOverlayInterface.cpp | 18 ++-- .../entities/src/EntityItemProperties.cpp | 9 +- libraries/entities/src/EntityTree.cpp | 44 +++----- 4 files changed, 64 insertions(+), 108 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 03cb9ff893..17e788c9b4 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -165,12 +165,6 @@ bool writeKeys(const char* filename, EC_KEY* keys) { return retval; } -// copied (without emits for various signals) from libraries/networking/src/RSAKeypairGenerator.cpp. -// We will have a different implementation in practice, but this gives us a start for now -// -// TODO: we don't really use the private keys returned - we can see how this evolves, but probably -// we should just return a list of public keys? -// or perhaps return the RSA* instead? QPair generateECKeypair() { EC_KEY* keyPair = EC_KEY_new_by_curve_name(NID_secp256k1); @@ -261,7 +255,7 @@ QByteArray readPublicKey(const char* filename) { } // the private key should be read/copied into heap memory. For now, we need the EC_KEY struct -// so I'll return that. Note we need to RSA_free(key) later!!! +// so I'll return that. EC_KEY* readPrivateKey(const char* filename) { FILE* fp; EC_KEY* key = NULL; @@ -552,24 +546,15 @@ QString Wallet::signWithKey(const QByteArray& text, const QString& key) { QByteArray hashedPlaintext = QCryptographicHash::hash(text, QCryptographicHash::Sha256); - int Return = ECDSA_sign(0, + int retrn = ECDSA_sign(0, reinterpret_cast(hashedPlaintext.constData()), hashedPlaintext.size(), reinterpret_cast(signature.data()), &signatureBytes, ecPrivateKey); - //Previous pattern, retained by ECDSA_sign - //int encryptReturn = RSA_sign(NID_sha256, - // reinterpret_cast(hashedPlaintext.constData()), - // hashedPlaintext.size(), - // reinterpret_cast(signature.data()), - // &signatureBytes, - // rsaPrivateKey); - - // free the private key RSA struct now that we are done with it EC_KEY_free(ecPrivateKey); - if (Return != -1) { + if (retrn != -1) { return signature.toBase64(); } } @@ -714,25 +699,24 @@ bool Wallet::changePassphrase(const QString& newPassphrase) { void Wallet::handleChallengeOwnershipPacket(QSharedPointer packet, SharedNodePointer sendingNode) { auto nodeList = DependencyManager::get(); - //With EC keys, we receive a nonce from the metaverse server, which is signed - //here with the private key and returned. Verification is done at server. + // With EC keys, we receive a nonce from the metaverse server, which is signed + // here with the private key and returned. Verification is done at server. bool challengeOriginatedFromClient = packet->getType() == PacketType::ChallengeOwnershipRequest; - //unsigned char decryptedText[64]; - int Status; + int status; int certIDByteArraySize; - int TextByteArraySize; + int textByteArraySize; int challengingNodeUUIDByteArraySize; packet->readPrimitive(&certIDByteArraySize); - packet->readPrimitive(&TextByteArraySize); //rerturns a cast char*, size + packet->readPrimitive(&textByteArraySize); // returns a cast char*, size if (challengeOriginatedFromClient) { packet->readPrimitive(&challengingNodeUUIDByteArraySize); } - //"encryptedText" is now a series of random bytes, a nonce + // "encryptedText" is now a series of random bytes, a nonce QByteArray certID = packet->read(certIDByteArraySize); - QByteArray Text = packet->read(TextByteArraySize); + QByteArray text = packet->read(textByteArraySize); QByteArray challengingNodeUUID; if (challengeOriginatedFromClient) { challengingNodeUUID = packet->read(challengingNodeUUIDByteArraySize); @@ -740,65 +724,56 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack EC_KEY* ec = readKeys(keyFilePath().toStdString().c_str()); QString sig; - // int decryptionStatus = -1; if (ec) { ERR_clear_error(); - sig = signWithKey(Text, ""); //base64 signature, QByteArray cast - //upon return to QString - - // decryptionStatus = RSA_private_decrypt(encryptedTextByteArraySize, - // reinterpret_cast(encryptedText.constData()), - // decryptedText, //unsigned char* - // ec, - // RSA_PKCS1_OAEP_PADDING); - - // EC_KEY_free(ec); - Status = 1; + sig = signWithKey(text, ""); // base64 signature, QByteArray cast (on return) to QString + status = 1; } else { qCDebug(commerce) << "During entity ownership challenge, creating the EC-signed nonce failed."; - Status = -1; + status = -1; } - + + EC_KEY_free(ec); QByteArray ba = sig.toLocal8Bit(); const char *sigChar = ba.data(); - QByteArray TextByteArray; - // if (decryptionStatus > -1) { - TextByteArray = QByteArray(sigChar, Status); - //} - TextByteArraySize = TextByteArray.size(); + QByteArray textByteArray; + if (status > -1) { + textByteArray = QByteArray(sigChar, status); + } + textByteArraySize = textByteArray.size(); int certIDSize = certID.size(); // setup the packet if (challengeOriginatedFromClient) { - auto TextPacket = NLPacket::create(PacketType::ChallengeOwnershipReply, - certIDSize + TextByteArraySize + challengingNodeUUIDByteArraySize + 3 * sizeof(int), + auto textPacket = NLPacket::create(PacketType::ChallengeOwnershipReply, + certIDSize + textByteArraySize + challengingNodeUUIDByteArraySize + 3 * sizeof(int), true); - TextPacket->writePrimitive(certIDSize); - TextPacket->writePrimitive(TextByteArraySize); - TextPacket->writePrimitive(challengingNodeUUIDByteArraySize); - TextPacket->write(certID); - TextPacket->write(TextByteArray); - TextPacket->write(challengingNodeUUID); + textPacket->writePrimitive(certIDSize); + textPacket->writePrimitive(textByteArraySize); + textPacket->writePrimitive(challengingNodeUUIDByteArraySize); + textPacket->write(certID); + textPacket->write(textByteArray); + textPacket->write(challengingNodeUUID); - qCDebug(commerce) << "Sending ChallengeOwnershipReply Packet containing signed text" << TextByteArray << "for CertID" << certID; + qCDebug(commerce) << "Sending ChallengeOwnershipReply Packet containing signed text" << textByteArray << "for CertID" << certID; - nodeList->sendPacket(std::move(TextPacket), *sendingNode); + nodeList->sendPacket(std::move(textPacket), *sendingNode); } else { - auto TextPacket = NLPacket::create(PacketType::ChallengeOwnership, certIDSize + TextByteArraySize + 2 * sizeof(int), true); + auto textPacket = NLPacket::create(PacketType::ChallengeOwnership, certIDSize + textByteArraySize + 2 * sizeof(int), true); - TextPacket->writePrimitive(certIDSize); - TextPacket->writePrimitive(TextByteArraySize); - TextPacket->write(certID); - TextPacket->write(TextByteArray); + textPacket->writePrimitive(certIDSize); + textPacket->writePrimitive(textByteArraySize); + textPacket->write(certID); + textPacket->write(textByteArray); - qCDebug(commerce) << "Sending ChallengeOwnership Packet containing signed text" << TextByteArray << "for CertID" << certID; + qCDebug(commerce) << "Sending ChallengeOwnership Packet containing signed text" << textByteArray << "for CertID" << certID; - nodeList->sendPacket(std::move(TextPacket), *sendingNode); + nodeList->sendPacket(std::move(textPacket), *sendingNode); } - if (Status == -1) { + if (status == -1) { qCDebug(commerce) << "During entity ownership challenge, signing the text failed."; long error = ERR_get_error(); if (error != 0) { diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index 2b2496b32a..8e7bca814d 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -323,21 +323,21 @@ void ContextOverlayInterface::openInspectionCertificate() { QString ownerKey = jsonObject["transfer_recipient_key"].toString(); QByteArray certID = entityProperties.getCertificateID().toUtf8(); - QByteArray Text = DependencyManager::get()->getTree()->computeNonce(certID, ownerKey); + QByteArray text = DependencyManager::get()->getTree()->computeNonce(certID, ownerKey); QByteArray nodeToChallengeByteArray = entityProperties.getOwningAvatarID().toRfc4122(); int certIDByteArraySize = certID.length(); - int TextByteArraySize = Text.length(); + int textByteArraySize = text.length(); int nodeToChallengeByteArraySize = nodeToChallengeByteArray.length(); auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnershipRequest, - certIDByteArraySize + TextByteArraySize + nodeToChallengeByteArraySize + 3 * sizeof(int), + certIDByteArraySize + textByteArraySize + nodeToChallengeByteArraySize + 3 * sizeof(int), true); challengeOwnershipPacket->writePrimitive(certIDByteArraySize); - challengeOwnershipPacket->writePrimitive(TextByteArraySize); + challengeOwnershipPacket->writePrimitive(textByteArraySize); challengeOwnershipPacket->writePrimitive(nodeToChallengeByteArraySize); challengeOwnershipPacket->write(certID); - challengeOwnershipPacket->write(Text); + challengeOwnershipPacket->write(text); challengeOwnershipPacket->write(nodeToChallengeByteArray); nodeList->sendPacket(std::move(challengeOwnershipPacket), *entityServer); @@ -418,16 +418,16 @@ void ContextOverlayInterface::handleChallengeOwnershipReplyPacket(QSharedPointer _challengeOwnershipTimeoutTimer.stop(); int certIDByteArraySize; - int TextByteArraySize; + int textByteArraySize; packet->readPrimitive(&certIDByteArraySize); - packet->readPrimitive(&TextByteArraySize); + packet->readPrimitive(&textByteArraySize); QString certID(packet->read(certIDByteArraySize)); - QString Text(packet->read(TextByteArraySize)); + QString text(packet->read(textByteArraySize)); EntityItemID id; - bool verificationSuccess = DependencyManager::get()->getTree()->verifyNonce(certID, Text, id); + bool verificationSuccess = DependencyManager::get()->getTree()->verifyNonce(certID, text, id); if (verificationSuccess) { emit ledger->updateCertificateStatus(certID, (uint)(ledger->CERTIFICATE_STATUS_VERIFICATION_SUCCESS)); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 2922be3cd4..4da27e15c0 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -13,9 +13,7 @@ #include #include #include - #include - #include #include #include @@ -27,7 +25,6 @@ #include #include #include - #include "EntitiesLogging.h" #include "EntityItem.h" #include "EntityItemProperties.h" @@ -2534,9 +2531,9 @@ bool EntityItemProperties::verifyStaticCertificateProperties() { int signatureLength = signatureByteArray.length(); ERR_clear_error(); - //ECSDA verification prototype: note that type is currently ignored - //int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen, - // const unsigned char *sig, int siglen, EC_KEY *eckey); + // ECSDA verification prototype: note that type is currently ignored + // int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen, + // const unsigned char *sig, int siglen, EC_KEY *eckey); bool answer = ECDSA_verify(0, digest, digestLength, diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index a5027e68a4..e152eea049 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -12,9 +12,7 @@ #include "EntityTree.h" #include #include - #include -//#include #include #include #include @@ -1177,23 +1175,9 @@ QByteArray EntityTree::computeNonce(const QString& certID, const QString ownerKe QUuid nonce = QUuid::createUuid(); //random, 5-hex value, separated by "-" QByteArray nonceBytes = nonce.toByteArray(); - //const unsigned int textLength = nonce.toString().length(); - //QByteArray encryptedText(ECDSA_size(ec), 0); - //const int encryptStatus = RSA_public_encrypt(textLength, - // reinterpret_cast(qPrintable(nonce.toString())), - // reinterpret_cast(encryptedText.data()), - // rsa, - // RSA_PKCS1_OAEP_PADDING); if (bio) { BIO_free(bio); } - //rsa_free(ec); - // if (encryptStatus == -1) { - // long error = ERR_get_error(); - // const char* error_str = ERR_error_string(error, NULL); - // qCWarning(entities) << "Unable to compute nonce for" << certID << "\nECDSA error:" << error_str; - // return ""; - //} QWriteLocker locker(&_certNonceMapLock); _certNonceMap.insert(certID, nonce); @@ -1207,7 +1191,7 @@ QByteArray EntityTree::computeNonce(const QString& certID, const QString ownerKe } } -bool EntityTree::verifyNonce(const QString& certID, const QString& Nonce, EntityItemID& id) { +bool EntityTree::verifyNonce(const QString& certID, const QString& nonce, EntityItemID& id) { { QReadLocker certIdMapLocker(&_entityCertificateIDMapLock); id = _entityCertificateIDMap.value(certID); @@ -1219,13 +1203,13 @@ bool EntityTree::verifyNonce(const QString& certID, const QString& Nonce, Entity actualNonce = _certNonceMap.take(certID).toString(); } - bool verificationSuccess = (actualNonce == Nonce); + bool verificationSuccess = (actualNonce == nonce); if (verificationSuccess) { qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "succeeded."; } else { qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "failed." - << "\nActual nonce:" << actualNonce << "\nonce:" << Nonce; + << "\nActual nonce:" << actualNonce << "\nonce:" << nonce; } return verificationSuccess; @@ -1251,24 +1235,24 @@ void EntityTree::processChallengeOwnershipReplyPacket(ReceivedMessage& message, auto nodeList = DependencyManager::get(); int certIDByteArraySize; - int TextByteArraySize; + int textByteArraySize; int challengingNodeUUIDByteArraySize; message.readPrimitive(&certIDByteArraySize); - message.readPrimitive(&TextByteArraySize); + message.readPrimitive(&textByteArraySize); message.readPrimitive(&challengingNodeUUIDByteArraySize); QByteArray certID(message.read(certIDByteArraySize)); - QByteArray Text(message.read(TextByteArraySize)); + QByteArray text(message.read(textByteArraySize)); QUuid challengingNode = QUuid::fromRfc4122(message.read(challengingNodeUUIDByteArraySize)); auto challengeOwnershipReplyPacket = NLPacket::create(PacketType::ChallengeOwnershipReply, - certIDByteArraySize + Text.length() + 2 * sizeof(int), + certIDByteArraySize + text.length() + 2 * sizeof(int), true); challengeOwnershipReplyPacket->writePrimitive(certIDByteArraySize); - challengeOwnershipReplyPacket->writePrimitive(Text.length()); + challengeOwnershipReplyPacket->writePrimitive(text.length()); challengeOwnershipReplyPacket->write(certID); - challengeOwnershipReplyPacket->write(Text); + challengeOwnershipReplyPacket->write(text); nodeList->sendPacket(std::move(challengeOwnershipReplyPacket), *(nodeList->nodeWithUUID(challengingNode))); } @@ -1277,9 +1261,9 @@ void EntityTree::sendChallengeOwnershipPacket(const QString& certID, const QStri // 1. Obtain a nonce auto nodeList = DependencyManager::get(); - QByteArray Text = computeNonce(certID, ownerKey); + QByteArray text = computeNonce(certID, ownerKey); - if (Text == "") { + if (text == "") { qCDebug(entities) << "CRITICAL ERROR: Couldn't compute nonce. Deleting entity..."; deleteEntity(entityItemID, true); } else { @@ -1288,12 +1272,12 @@ void EntityTree::sendChallengeOwnershipPacket(const QString& certID, const QStri QByteArray certIDByteArray = certID.toUtf8(); int certIDByteArraySize = certIDByteArray.size(); auto challengeOwnershipPacket = NLPacket::create(PacketType::ChallengeOwnership, - certIDByteArraySize + Text.length() + 2 * sizeof(int), + certIDByteArraySize + text.length() + 2 * sizeof(int), true); challengeOwnershipPacket->writePrimitive(certIDByteArraySize); - challengeOwnershipPacket->writePrimitive(Text.length()); + challengeOwnershipPacket->writePrimitive(text.length()); challengeOwnershipPacket->write(certIDByteArray); - challengeOwnershipPacket->write(Text); + challengeOwnershipPacket->write(text); nodeList->sendPacket(std::move(challengeOwnershipPacket), *senderNode); // 3. Kickoff a 10-second timeout timer that deletes the entity if we don't get an ownership response in time From 28eedd1a94b6ad066d2822da760a21429078e59d Mon Sep 17 00:00:00 2001 From: H Q Date: Fri, 17 Nov 2017 11:30:21 -0800 Subject: [PATCH 05/30] Small style mod --- libraries/entities/src/EntityItemProperties.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 4da27e15c0..762e13d8a1 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -16,11 +16,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include From 899999a4c6a00b6d415056ace7b301c639e94ec1 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 22 Nov 2017 15:58:30 -0800 Subject: [PATCH 06/30] fix up dynamic ownership challenge --- interface/src/commerce/Wallet.cpp | 8 +- libraries/entities/src/EntityTree.cpp | 111 ++++++++++++++++++++------ libraries/entities/src/EntityTree.h | 3 +- 3 files changed, 91 insertions(+), 31 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 17e788c9b4..98a27cd5cc 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -537,7 +537,7 @@ QStringList Wallet::listPublicKeys() { // the horror of code pages and so on (changing the bytes) by just returning a base64 // encoded string representing the signature (suitable for http, etc...) QString Wallet::signWithKey(const QByteArray& text, const QString& key) { - qCInfo(commerce) << "Signing text."; + qCInfo(commerce) << "Signing text" << text << "with key" << key; EC_KEY* ecPrivateKey = NULL; if ((ecPrivateKey = readPrivateKey(keyFilePath().toStdString().c_str()))) { QByteArray signature(ECDSA_size(ecPrivateKey), 0); @@ -727,7 +727,7 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack if (ec) { ERR_clear_error(); - sig = signWithKey(text, ""); // base64 signature, QByteArray cast (on return) to QString + sig = signWithKey(text, ""); // base64 signature, QByteArray cast (on return) to QString FIXME should pass ec as string so we can tell which key to sign with status = 1; } else { qCDebug(commerce) << "During entity ownership challenge, creating the EC-signed nonce failed."; @@ -740,7 +740,7 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack QByteArray textByteArray; if (status > -1) { - textByteArray = QByteArray(sigChar, status); + textByteArray = QByteArray(sigChar, (int) strlen(sigChar)); } textByteArraySize = textByteArray.size(); int certIDSize = certID.size(); @@ -768,7 +768,7 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack textPacket->write(certID); textPacket->write(textByteArray); - qCDebug(commerce) << "Sending ChallengeOwnership Packet containing signed text" << textByteArray << "for CertID" << certID; + qCDebug(commerce) << "Sending ChallengeOwnershipReply Packet containing signed text" << textByteArray << "for CertID" << certID; nodeList->sendPacket(std::move(textPacket), *sendingNode); } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 2ef0d319ee..bd446ab332 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1166,29 +1166,13 @@ void EntityTree::startPendingTransferStatusTimer(const QString& certID, const En } QByteArray EntityTree::computeNonce(const QString& certID, const QString ownerKey) { - QString ownerKeyWithHeaders = ("-----BEGIN ECDSA PUBLIC KEY-----\n" + ownerKey + "\n-----END ECDSA PUBLIC KEY-----"); - BIO* bio = BIO_new_mem_buf((void*)ownerKeyWithHeaders.toUtf8().constData(), -1); - BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); // NO NEWLINE - EC_KEY* ec = PEM_read_bio_EC_PUBKEY(bio, NULL, NULL, NULL); + QUuid nonce = QUuid::createUuid(); //random, 5-hex value, separated by "-" + QByteArray nonceBytes = nonce.toByteArray(); - if (ec) { - QUuid nonce = QUuid::createUuid(); //random, 5-hex value, separated by "-" - QByteArray nonceBytes = nonce.toByteArray(); + QWriteLocker locker(&_certNonceMapLock); + _certNonceMap.insert(certID, QPair(nonce, ownerKey)); - if (bio) { - BIO_free(bio); - } - - QWriteLocker locker(&_certNonceMapLock); - _certNonceMap.insert(certID, nonce); - - return nonceBytes; - } else { - if (bio) { - BIO_free(bio); - } - return ""; - } + return nonceBytes; } bool EntityTree::verifyNonce(const QString& certID, const QString& nonce, EntityItemID& id) { @@ -1197,24 +1181,99 @@ bool EntityTree::verifyNonce(const QString& certID, const QString& nonce, Entity id = _entityCertificateIDMap.value(certID); } - QString actualNonce; + QString actualNonce, key; { QWriteLocker locker(&_certNonceMapLock); - actualNonce = _certNonceMap.take(certID).toString(); + QPair sent = _certNonceMap.take(certID); + actualNonce = sent.first.toString(); + key = sent.second; } - bool verificationSuccess = (actualNonce == nonce); + QString annotatedKey = "-----BEGIN PUBLIC KEY-----\n" + key + "\n-----END PUBLIC KEY-----"; + bool verificationSuccess = verifySignature(annotatedKey.toUtf8(), actualNonce.toUtf8(), nonce.toUtf8()); if (verificationSuccess) { qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "succeeded."; } else { - qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "failed." - << "\nActual nonce:" << actualNonce << "\nonce:" << nonce; + qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "failed for nonce" << actualNonce << "key" << key << "signature" << nonce; } return verificationSuccess; } +// FIXME: This is largely copied from EntityItemProperties::verifyStaticCertificateProperties, which should be refactored to use this. +// I also don't like the nested-if style, but for this step I'm deliberately preserving the similarity. +bool EntityTree::verifySignature(const QString& publicKey, const QByteArray& digestByteArray, const QByteArray& signatureByteArray) { + + if (digestByteArray.isEmpty()) { + return false; + } + + const unsigned char* key = reinterpret_cast(publicKey.toUtf8().constData()); + int keyLength = publicKey.length(); + + BIO *bio = BIO_new_mem_buf((void*)key, keyLength); + EVP_PKEY* evp_key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); + if (evp_key) { + EC_KEY* ec = EVP_PKEY_get1_EC_KEY(evp_key); + if (ec) { + const unsigned char* digest = reinterpret_cast(digestByteArray.constData()); + int digestLength = digestByteArray.length(); + + const unsigned char* signature = reinterpret_cast(signatureByteArray.constData()); + int signatureLength = signatureByteArray.length(); + + ERR_clear_error(); + // ECSDA verification prototype: note that type is currently ignored + // int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen, + // const unsigned char *sig, int siglen, EC_KEY *eckey); + bool answer = ECDSA_verify(0, + digest, + digestLength, + signature, + signatureLength, + ec); + long error = ERR_get_error(); + if (error != 0) { + const char* error_str = ERR_error_string(error, NULL); + qCWarning(entities) << "ERROR while verifying signature! EC error:" << error_str + << "\nKey:" << publicKey << "\nutf8 Key Length:" << keyLength + << "\nDigest:" << digest << "\nDigest Length:" << digestLength + << "\nSignature:" << signature << "\nSignature Length:" << signatureLength; + } + EC_KEY_free(ec); + if (bio) { + BIO_free(bio); + } + if (evp_key) { + EVP_PKEY_free(evp_key); + } + return answer; + } + else { + if (bio) { + BIO_free(bio); + } + if (evp_key) { + EVP_PKEY_free(evp_key); + } + long error = ERR_get_error(); + const char* error_str = ERR_error_string(error, NULL); + qCWarning(entities) << "Failed to verify signature! key" << publicKey << " EC key error:" << error_str; + return false; + } + } + else { + if (bio) { + BIO_free(bio); + } + long error = ERR_get_error(); + const char* error_str = ERR_error_string(error, NULL); + qCWarning(entities) << "Failed to verify signature! key" << publicKey << " EC PEM error:" << error_str; + return false; + } +} + void EntityTree::processChallengeOwnershipRequestPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { int certIDByteArraySize; int textByteArraySize; diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index a8bca1fdef..747a73ebd7 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -277,6 +277,7 @@ public: QByteArray computeNonce(const QString& certID, const QString ownerKey); bool verifyNonce(const QString& certID, const QString& nonce, EntityItemID& id); + static bool verifySignature(const QString& key, const QByteArray& text, const QByteArray& signature); void setMyAvatar(std::shared_ptr myAvatar) { _myAvatar = myAvatar; } @@ -334,7 +335,7 @@ protected: QHash _entityCertificateIDMap; mutable QReadWriteLock _certNonceMapLock; - QHash _certNonceMap; + QHash> _certNonceMap; EntitySimulationPointer _simulation; From abf41300dd6417fb8ee1e516a29b689ace09f0d4 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 22 Nov 2017 16:29:56 -0800 Subject: [PATCH 07/30] refactor --- .../entities/src/EntityItemProperties.cpp | 38 +++++----- libraries/entities/src/EntityItemProperties.h | 1 + libraries/entities/src/EntityTree.cpp | 75 +------------------ libraries/entities/src/EntityTree.h | 1 - 4 files changed, 23 insertions(+), 92 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 762e13d8a1..11b83e1052 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -2505,28 +2505,25 @@ QByteArray EntityItemProperties::getStaticCertificateHash() const { return QCryptographicHash::hash(getStaticCertificateJSON(), QCryptographicHash::Sha256); } -bool EntityItemProperties::verifyStaticCertificateProperties() { - // True IIF a non-empty certificateID matches the static certificate json. - // I.e., if we can verify that the certificateID was produced by High Fidelity signing the static certificate hash. +// FIXME: This is largely copied from EntityItemProperties::verifyStaticCertificateProperties, which should be refactored to use this. +// I also don't like the nested-if style, but for this step I'm deliberately preserving the similarity. +bool EntityItemProperties::verifySignature(const QString& publicKey, const QByteArray& digestByteArray, const QByteArray& signatureByteArray) { - if (getCertificateID().isEmpty()) { + if (digestByteArray.isEmpty()) { return false; } - const QByteArray marketplacePublicKeyByteArray = EntityItem::_marketplacePublicKey.toUtf8(); - const unsigned char* marketplacePublicKey = reinterpret_cast(marketplacePublicKeyByteArray.constData()); - int marketplacePublicKeyLength = marketplacePublicKeyByteArray.length(); + const unsigned char* key = reinterpret_cast(publicKey.toUtf8().constData()); + int keyLength = publicKey.length(); - BIO *bio = BIO_new_mem_buf((void*)marketplacePublicKey, marketplacePublicKeyLength); + BIO *bio = BIO_new_mem_buf((void*)key, keyLength); EVP_PKEY* evp_key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); if (evp_key) { EC_KEY* ec = EVP_PKEY_get1_EC_KEY(evp_key); if (ec) { - const QByteArray digestByteArray = getStaticCertificateHash(); const unsigned char* digest = reinterpret_cast(digestByteArray.constData()); int digestLength = digestByteArray.length(); - const QByteArray signatureByteArray = QByteArray::fromBase64(getCertificateID().toUtf8()); const unsigned char* signature = reinterpret_cast(signatureByteArray.constData()); int signatureLength = signatureByteArray.length(); @@ -2543,9 +2540,8 @@ bool EntityItemProperties::verifyStaticCertificateProperties() { long error = ERR_get_error(); if (error != 0) { const char* error_str = ERR_error_string(error, NULL); - qCWarning(entities) << "ERROR while verifying static certificate properties! EC error:" << error_str - << "\nStatic Cert JSON:" << getStaticCertificateJSON() - << "\nKey:" << EntityItem::_marketplacePublicKey << "\nKey Length:" << marketplacePublicKeyLength + qCWarning(entities) << "ERROR while verifying signature! EC error:" << error_str + << "\nKey:" << publicKey << "\nutf8 Key Length:" << keyLength << "\nDigest:" << digest << "\nDigest Length:" << digestLength << "\nSignature:" << signature << "\nSignature Length:" << signatureLength; } @@ -2557,7 +2553,8 @@ bool EntityItemProperties::verifyStaticCertificateProperties() { EVP_PKEY_free(evp_key); } return answer; - } else { + } + else { if (bio) { BIO_free(bio); } @@ -2566,16 +2563,23 @@ bool EntityItemProperties::verifyStaticCertificateProperties() { } long error = ERR_get_error(); const char* error_str = ERR_error_string(error, NULL); - qCWarning(entities) << "Failed to verify static certificate properties! EC error:" << error_str; + qCWarning(entities) << "Failed to verify signature! key" << publicKey << " EC key error:" << error_str; return false; } - } else { + } + else { if (bio) { BIO_free(bio); } long error = ERR_get_error(); const char* error_str = ERR_error_string(error, NULL); - qCWarning(entities) << "Failed to verify static certificate properties! EC error:" << error_str; + qCWarning(entities) << "Failed to verify signature! key" << publicKey << " EC PEM error:" << error_str; return false; } } + +bool EntityItemProperties::verifyStaticCertificateProperties() { + // True IIF a non-empty certificateID matches the static certificate json. + // I.e., if we can verify that the certificateID was produced by High Fidelity signing the static certificate hash. + return verifySignature(EntityItem::_marketplacePublicKey, getStaticCertificateHash(), QByteArray::fromBase64(getCertificateID().toUtf8())); +} diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 732dbdf69f..ec192d7c9f 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -339,6 +339,7 @@ public: QByteArray getStaticCertificateJSON() const; QByteArray getStaticCertificateHash() const; bool verifyStaticCertificateProperties(); + static bool verifySignature(const QString& key, const QByteArray& text, const QByteArray& signature); protected: QString getCollisionMaskAsString() const; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index bd446ab332..fb27209de4 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1190,7 +1190,7 @@ bool EntityTree::verifyNonce(const QString& certID, const QString& nonce, Entity } QString annotatedKey = "-----BEGIN PUBLIC KEY-----\n" + key + "\n-----END PUBLIC KEY-----"; - bool verificationSuccess = verifySignature(annotatedKey.toUtf8(), actualNonce.toUtf8(), nonce.toUtf8()); + bool verificationSuccess = EntityItemProperties::verifySignature(annotatedKey.toUtf8(), actualNonce.toUtf8(), nonce.toUtf8()); if (verificationSuccess) { qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "succeeded."; @@ -1201,79 +1201,6 @@ bool EntityTree::verifyNonce(const QString& certID, const QString& nonce, Entity return verificationSuccess; } -// FIXME: This is largely copied from EntityItemProperties::verifyStaticCertificateProperties, which should be refactored to use this. -// I also don't like the nested-if style, but for this step I'm deliberately preserving the similarity. -bool EntityTree::verifySignature(const QString& publicKey, const QByteArray& digestByteArray, const QByteArray& signatureByteArray) { - - if (digestByteArray.isEmpty()) { - return false; - } - - const unsigned char* key = reinterpret_cast(publicKey.toUtf8().constData()); - int keyLength = publicKey.length(); - - BIO *bio = BIO_new_mem_buf((void*)key, keyLength); - EVP_PKEY* evp_key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); - if (evp_key) { - EC_KEY* ec = EVP_PKEY_get1_EC_KEY(evp_key); - if (ec) { - const unsigned char* digest = reinterpret_cast(digestByteArray.constData()); - int digestLength = digestByteArray.length(); - - const unsigned char* signature = reinterpret_cast(signatureByteArray.constData()); - int signatureLength = signatureByteArray.length(); - - ERR_clear_error(); - // ECSDA verification prototype: note that type is currently ignored - // int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen, - // const unsigned char *sig, int siglen, EC_KEY *eckey); - bool answer = ECDSA_verify(0, - digest, - digestLength, - signature, - signatureLength, - ec); - long error = ERR_get_error(); - if (error != 0) { - const char* error_str = ERR_error_string(error, NULL); - qCWarning(entities) << "ERROR while verifying signature! EC error:" << error_str - << "\nKey:" << publicKey << "\nutf8 Key Length:" << keyLength - << "\nDigest:" << digest << "\nDigest Length:" << digestLength - << "\nSignature:" << signature << "\nSignature Length:" << signatureLength; - } - EC_KEY_free(ec); - if (bio) { - BIO_free(bio); - } - if (evp_key) { - EVP_PKEY_free(evp_key); - } - return answer; - } - else { - if (bio) { - BIO_free(bio); - } - if (evp_key) { - EVP_PKEY_free(evp_key); - } - long error = ERR_get_error(); - const char* error_str = ERR_error_string(error, NULL); - qCWarning(entities) << "Failed to verify signature! key" << publicKey << " EC key error:" << error_str; - return false; - } - } - else { - if (bio) { - BIO_free(bio); - } - long error = ERR_get_error(); - const char* error_str = ERR_error_string(error, NULL); - qCWarning(entities) << "Failed to verify signature! key" << publicKey << " EC PEM error:" << error_str; - return false; - } -} - void EntityTree::processChallengeOwnershipRequestPacket(ReceivedMessage& message, const SharedNodePointer& sourceNode) { int certIDByteArraySize; int textByteArraySize; diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 747a73ebd7..11a747d624 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -277,7 +277,6 @@ public: QByteArray computeNonce(const QString& certID, const QString ownerKey); bool verifyNonce(const QString& certID, const QString& nonce, EntityItemID& id); - static bool verifySignature(const QString& key, const QByteArray& text, const QByteArray& signature); void setMyAvatar(std::shared_ptr myAvatar) { _myAvatar = myAvatar; } From a6b437a79f01b3e76ce068f6b595b700cc77f608 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 22 Nov 2017 16:55:57 -0800 Subject: [PATCH 08/30] get rid of "error" warning because the key wasn't broken into 64 char lines --- libraries/entities/src/EntityTree.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index fb27209de4..e62399ce95 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1189,7 +1189,7 @@ bool EntityTree::verifyNonce(const QString& certID, const QString& nonce, Entity key = sent.second; } - QString annotatedKey = "-----BEGIN PUBLIC KEY-----\n" + key + "\n-----END PUBLIC KEY-----"; + QString annotatedKey = "-----BEGIN PUBLIC KEY-----\n" + key.insert(64, "\n") + "\n-----END PUBLIC KEY-----"; bool verificationSuccess = EntityItemProperties::verifySignature(annotatedKey.toUtf8(), actualNonce.toUtf8(), nonce.toUtf8()); if (verificationSuccess) { From 1575119327717ffbe2166dcd02984233b06293ea Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Mon, 27 Nov 2017 10:46:57 -0800 Subject: [PATCH 09/30] PR feedback --- interface/src/commerce/Wallet.cpp | 2 +- libraries/entities/src/EntityItemProperties.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 98a27cd5cc..d6190aa7a0 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -768,7 +768,7 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack textPacket->write(certID); textPacket->write(textByteArray); - qCDebug(commerce) << "Sending ChallengeOwnershipReply Packet containing signed text" << textByteArray << "for CertID" << certID; + qCDebug(commerce) << "Sending ChallengeOwnership Packet containing signed text" << textByteArray << "for CertID" << certID; nodeList->sendPacket(std::move(textPacket), *sendingNode); } diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 11b83e1052..6ec5e8eb05 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -2579,7 +2579,7 @@ bool EntityItemProperties::verifySignature(const QString& publicKey, const QByte } bool EntityItemProperties::verifyStaticCertificateProperties() { - // True IIF a non-empty certificateID matches the static certificate json. + // True IFF a non-empty certificateID matches the static certificate json. // I.e., if we can verify that the certificateID was produced by High Fidelity signing the static certificate hash. return verifySignature(EntityItem::_marketplacePublicKey, getStaticCertificateHash(), QByteArray::fromBase64(getCertificateID().toUtf8())); } From d769acd3450a5b2bd151b2ac7b5593f5354cadff Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 16 Nov 2017 12:44:11 -0800 Subject: [PATCH 10/30] Updating Android toolchain --- .gitignore | 4 +- BUILD_ANDROID.md | 152 +++------- android/app/CMakeLists.txt | 6 +- android/app/build.gradle | 22 +- android/app/src/main/AndroidManifest.xml | 11 +- android/app/src/main/cpp/renderer.cpp | 259 ++++++------------ android/app/src/main/cpp/renderer.h | 2 +- .../saintandreas/testapp/MainActivity.java | 27 +- android/build.gradle | 106 +++---- android/setupGVR.gradle | 41 +++ android/setupOpenSSL.gradle | 26 ++ android/setupQt.gradle | 63 +++++ android/setupScribe.gradle | 27 ++ android/setupTBB.gradle | 31 +++ cmake/macros/TargetOpenSSL.cmake | 7 +- cmake/macros/TargetTBB.cmake | 8 +- libraries/networking/src/AssetUtils.cpp | 1 + .../networking/src/DataServerAccountInfo.cpp | 3 +- libraries/networking/src/LimitedNodeList.cpp | 1 + 19 files changed, 376 insertions(+), 421 deletions(-) create mode 100644 android/setupGVR.gradle create mode 100644 android/setupOpenSSL.gradle create mode 100644 android/setupQt.gradle create mode 100644 android/setupScribe.gradle create mode 100644 android/setupTBB.gradle diff --git a/.gitignore b/.gitignore index c1eef3817f..665238e7da 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,9 @@ Makefile # Android Studio *.iml local.properties -android/libraries +android/gradle* +android/.gradle +android/app/src/main/jniLibs # VSCode # List taken from Github Global Ignores master@435c4d92 diff --git a/BUILD_ANDROID.md b/BUILD_ANDROID.md index cc51e58b1d..5d2e6b9293 100644 --- a/BUILD_ANDROID.md +++ b/BUILD_ANDROID.md @@ -1,25 +1,23 @@ -Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only Android specific instructions are found in this file. +Please read the [general build guide](BUILD.md) for information on building other platform. Only Android specific instructions are found in this file. -# Android Dependencies +# Dependencies + +*Currently Android building is only supported on 64 bit Linux host environments* You will need the following tools to build our Android targets. -* [Qt](http://www.qt.io/download-open-source/#) ~> 5.9.1 +* [Gradle](https://gradle.org/install/) * [Android Studio](https://developer.android.com/studio/index.html) -* [Google VR SDK](https://github.com/googlevr/gvr-android-sdk/releases) -* [Gradle](https://gradle.org/releases/) -### Qt +### Gradle -Download the Qt online installer. Run the installer and select the android_armv7 binaries. Installing to the default path is recommended +Install gradle version 4.1 or higher. Following the instructions to install via [SDKMAN!](http://sdkman.io/install.html) is recommended. ### Android Studio Download the Android Studio installer and run it. Once installed, at the welcome screen, click configure in the lower right corner and select SDK manager -From the SDK Platforms tab, select API level 26. - -* Install the ARM EABI v7a System Image if you want to run an emulator. +From the SDK Platforms tab, select API levels 24 and 26. From the SDK Tools tab select the following @@ -29,123 +27,41 @@ From the SDK Tools tab select the following * LLDB * Android SDK Platform-Tools * Android SDK Tools -* Android SDK Tools * NDK (even if you have the NDK installed separately) -### Google VR SDK +# Environment -Download the 1.8 Google VR SDK [release](https://github.com/googlevr/gvr-android-sdk/archive/v1.80.0.zip). Unzip the archive to a location on your drive. - -### Gradle - -Download [Gradle 4.1](https://services.gradle.org/distributions/gradle-4.1-all.zip) and unzip it on your local drive. You may wish to add the location of the bin directory within the archive to your path +Setting up the environment for android builds requires some additional steps #### Set up machine specific Gradle properties -Create a `gradle.properties` file in ~/.gradle. Edit the file to contain the following +Create a `gradle.properties` file in $HOME/.gradle. Edit the file to contain the following - QT5_ROOT=C\:\\Qt\\5.9.1\\android_armv7 - GVR_ROOT=C\:\\Android\\gvr-android-sdk + HIFI_ANDROID_PRECOMPILED=/Android/hifi_externals -Replace the paths with your local installations of Qt5 and the Google VR SDK +Note, do not use `$HOME` for the path. It must be a fully qualified path name. + +### Setup the repository + +Clone the repository + +`git clone https://github.com/highfidelity/hifi.git` + +Enter the repository `android` directory + +`cd hifi/android` + +Execute a gradle pre-build setup. This step should only need to be done once + +`gradle setupDepedencies` -# TODO fix the rest +# Building & Running -You will also need to cross-compile the dependencies required for all platforms for Android, and help CMake find these compiled libraries on your machine. +* Open Android Studio +* Choose _Open Existing Android Studio Project_ +* Navigate to the `hifi` repository and choose the `android` folder and select _OK_ +* If Android Studio asks you if you want to use the Gradle wrapper, select cancel and tell it where your local gradle installation is. If you used SDKMAN to install gradle it will be located in `$HOME/.sdkman/candidates/gradle/current/` +* From the _Build_ menu select _Make Project_ +* Once the build completes, from the _Run_ menu select _Run App_ -#### Scribe - -High Fidelity has a shader pre-processing tool called `scribe` that various libraries will call on during the build process. You must compile scribe using your native toolchain (following the build instructions for your platform) and then pass a CMake variable or set an ENV variable `SCRIBE_PATH` that is a path to the scribe executable. - -CMake will fatally error if it does not find the scribe executable while using the android toolchain. - -#### Optional Components - -* [Oculus Mobile SDK](https://developer.oculus.com/downloads/#sdk=mobile) ~> 0.4.2 - -#### ANDROID_LIB_DIR - -Since you won't be installing Android dependencies to system paths on your development machine, CMake will need a little help tracking down your Android dependencies. - -This is most easily accomplished by installing all Android dependencies in the same folder. You can place this folder wherever you like on your machine. In this build guide and across our CMakeLists files this folder is referred to as `ANDROID_LIB_DIR`. You can set `ANDROID_LIB_DIR` in your environment or by passing when you run CMake. - -#### Qt - -Install Qt 5.5.1 for Android for your host environment from the [Qt downloads page](http://www.qt.io/download/). Install Qt to ``$ANDROID_LIB_DIR/Qt``. This is required so that our root CMakeLists file can help CMake find your Android Qt installation. - -The component required for the Android build is the `Android armv7` component. - -If you would like to install Qt to a different location, or attempt to build with a different Qt version, you can pass `ANDROID_QT_CMAKE_PREFIX_PATH` to CMake. Point to the `cmake` folder inside `$VERSION_NUMBER/android_armv7/lib`. Otherwise, our root CMakeLists will set it to `$ANDROID_LIB_DIR/Qt/5.5/android_armv7/lib/cmake`. - -#### OpenSSL - -Cross-compilation of OpenSSL has been tested from an OS X machine running 10.10 compiling OpenSSL 1.0.2. It is likely that the steps below will work for other OpenSSL versions than 1.0.2. - -The original instructions to compile OpenSSL for Android from your host environment can be found [here](http://wiki.openssl.org/index.php/Android). We required some tweaks to get OpenSSL to successfully compile, those tweaks are explained below. - -Download the [OpenSSL source](https://www.openssl.org/source/) and extract the tarball inside your `ANDROID_LIB_DIR`. Rename the extracted folder to `openssl`. - -You will need the [setenv-android.sh script](http://wiki.openssl.org/index.php/File:Setenv-android.sh) from the OpenSSL wiki. - -You must change three values at the top of the `setenv-android.sh` script - `_ANDROID_NDK`, `_ANDROID_EABI` and `_ANDROID_API`. -`_ANDROID_NDK` should be `android-ndk-r10`, `_ANDROID_EABI` should be `arm-linux-androidebi-4.9` and `_ANDROID_API` should be `19`. - -First, make sure `ANDROID_NDK_ROOT` is set in your env. This should be the path to the root of your Android NDK install. `setenv-android.sh` needs `ANDROID_NDK_ROOT` to set the environment variables required for building OpenSSL. - -Source the `setenv-android.sh` script so it can set environment variables that OpenSSL will use while compiling. If you use zsh as your shell you may need to modify the `setenv-android.sh` for it to set the correct variables in your env. - -``` -export ANDROID_NDK_ROOT=YOUR_NDK_ROOT -source setenv-android.sh -``` - -Then, from the OpenSSL directory, run the following commands. - -``` -perl -pi -e 's/install: all install_docs install_sw/install: install_docs install_sw/g' Makefile.org -./config shared -no-ssl2 -no-ssl3 -no-comp -no-hw -no-engine --openssldir=/usr/local/ssl/$ANDROID_API -make depend -make all -``` - -This should generate libcrypto and libssl in the root of the OpenSSL directory. YOU MUST remove the `libssl.so` and `libcrypto.so` files that are generated. They are symlinks to `libssl.so.VER` and `libcrypto.so.VER` which Android does not know how to handle. By removing `libssl.so` and `libcrypto.so` the FindOpenSSL module will find the static libs and use those instead. - -If you have been building other components it is possible that the OpenSSL compile will fail based on the values other cross-compilations (tbb, bullet) have set. Ensure that you are in a new terminal window to avoid compilation errors from previously set environment variables. - -#### Oculus Mobile SDK - -The Oculus Mobile SDK is optional, for Gear VR support. It is not required to compile gvr-interface. - -Download the [Oculus Mobile SDK](https://developer.oculus.com/downloads/#sdk=mobile) and extract the archive inside your `ANDROID_LIB_DIR` folder. Rename the extracted folder to `libovr`. - -From the VRLib directory, use ndk-build to build VrLib. - -``` -cd VRLib -ndk-build -``` - -This will create the liboculus.a archive that our FindLibOVR module will look for when cmake is run. - -##### Hybrid testing - -Currently the 'vr_dual' mode that would allow us to run a hybrid app has limited support in the Oculus Mobile SDK. The best way to have an application we can launch without having to connect to the GearVR is to put the Gear VR Service into developer mode. This stops Oculus Home from taking over the device when it is plugged into the Gear VR headset, and allows the application to be launched from the Applications page. - -To put the Gear VR Service into developer mode you need an application with an Oculus Signature File on your device. Generate an Oculus Signature File for your device on the [Oculus osig tool page](https://developer.oculus.com/tools/osig/). Place this file in the gvr-interface/assets directory. Cmake will automatically copy it into your apk in the right place when you execute `make gvr-interface-apk`. - -Once the application is on your device, go to `Settings->Application Manager->Gear VR Service->Manage Storage`. Tap on `VR Service Version` six times. It will scan your device to verify that you have an osig file in an application on your device, and then it will let you enable Developer mode. - -### CMake - -We use CMake to generate the makefiles that compile and deploy the Android APKs to your device. In order to create Makefiles for the Android targets, CMake requires that some environment variables are set, and that other variables are passed to it when it is run. - -The following must be set in your environment: - -* ANDROID_NDK - the root of your Android NDK install -* ANDROID_HOME - the root of your Android SDK install -* ANDROID_LIB_DIR - the directory containing cross-compiled versions of dependencies - -The following must be passed to CMake when it is run: - -* USE_ANDROID_TOOLCHAIN - set to true to build for Android diff --git a/android/app/CMakeLists.txt b/android/app/CMakeLists.txt index 2d6df925e9..65709f7547 100644 --- a/android/app/CMakeLists.txt +++ b/android/app/CMakeLists.txt @@ -1,8 +1,8 @@ set(TARGET_NAME native-lib) setup_hifi_library() -link_hifi_libraries(shared networking gl gpu gpu-gles render-utils) -autoscribe_shader_lib(gpu model render render-utils) +link_hifi_libraries(shared networking gl gpu gpu-gles) target_opengl() target_link_libraries(native-lib android log m) +set(GVR_ROOT "${HIFI_ANDROID_PRECOMPILED}/gvr/gvr-android-sdk-1.101.0/") target_include_directories(native-lib PRIVATE "${GVR_ROOT}/libraries/headers") -target_link_libraries(native-lib "C:/Users/bdavis/Git/hifi/android/libraries/jni/armeabi-v7a/libgvr.so") +target_link_libraries(native-lib "${HIFI_ANDROID_PRECOMPILED}/jni/arm64-v8a/libgvr.so") diff --git a/android/app/build.gradle b/android/app/build.gradle index bd1c596bf3..30b0bf78b4 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,27 +1,26 @@ + apply plugin: 'com.android.application' android { compileSdkVersion 26 - buildToolsVersion "26.0.1" defaultConfig { applicationId "org.saintandreas.testapp" minSdkVersion 24 targetSdkVersion 26 versionCode 1 versionName "1.0" - ndk { abiFilters 'armeabi-v7a' } + ndk { abiFilters 'arm64-v8a' } externalNativeBuild { cmake { arguments '-DHIFI_ANDROID=1', '-DANDROID_PLATFORM=android-24', '-DANDROID_TOOLCHAIN=clang', - '-DANDROID_STL=gnustl_shared', - '-DGVR_ROOT=' + GVR_ROOT, - '-DNATIVE_SCRIBE=c:/bin/scribe.exe', - "-DHIFI_ANDROID_PRECOMPILED=${project.rootDir}/libraries/jni/armeabi-v7a" + '-DANDROID_STL=c++_shared', + '-DQT_CMAKE_PREFIX_PATH=' + HIFI_ANDROID_PRECOMPILED + '/qt/lib/cmake', + '-DNATIVE_SCRIBE=' + HIFI_ANDROID_PRECOMPILED + '/scribe_linux_x86_64', + '-DHIFI_ANDROID_PRECOMPILED=' + HIFI_ANDROID_PRECOMPILED } } - jackOptions { enabled true } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -35,11 +34,6 @@ android { } } - sourceSets { - main { - jniLibs.srcDirs += '../libraries/jni'; - } - } externalNativeBuild { cmake { path '../../CMakeLists.txt' @@ -52,6 +46,4 @@ dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.google.vr:sdk-audio:1.80.0' compile 'com.google.vr:sdk-base:1.80.0' -} - -build.dependsOn(':extractQt5') +} \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 05547bd5ae..c96ac0ef90 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -7,12 +7,10 @@ - - - - - - - - diff --git a/android/app/src/main/cpp/renderer.cpp b/android/app/src/main/cpp/renderer.cpp index a877ebd777..9c9c9f8b52 100644 --- a/android/app/src/main/cpp/renderer.cpp +++ b/android/app/src/main/cpp/renderer.cpp @@ -3,20 +3,19 @@ #include #include + #include - -#include "GoogleVRHelpers.h" - #include -#include +#include + +#if 0 #include #include #include #include #include #include - #include #include #include @@ -57,7 +56,6 @@ #include #include -#if 0 #include #include #include @@ -68,6 +66,12 @@ #include #endif +#if defined(GVR) +#include +#include "GoogleVRHelpers.h" + +static const uint64_t kPredictionTimeWithoutVsyncNanos = 50000000; +static const gvr_rectf fullscreen = {0, 1, 0, 1}; template void withFrameBuffer(gvr::Frame& frame, int32_t index, F f) { @@ -76,60 +80,37 @@ void withFrameBuffer(gvr::Frame& frame, int32_t index, F f) { frame.Unbind(); } - -static const uint64_t kPredictionTimeWithoutVsyncNanos = 50000000; - -// Each shader has two variants: a single-eye ES 2.0 variant, and a multiview -// ES 3.0 variant. The multiview vertex shaders use transforms defined by -// arrays of mat4 uniforms, using gl_ViewID_OVR to determine the array index. - -#define UNIFORM_LIGHT_POS 20 -#define UNIFORM_M 16 -#define UNIFORM_MV 8 -#define UNIFORM_MVP 0 - -#if 0 -uniform Transform { // API uses “Transform[2]” to refer to instance 2 - mat4 u_MVP[2]; - mat4 u_MVMatrix[2]; - mat4 u_Model; - vec3 u_LightPos[2]; -}; -static const char *kDiffuseLightingVertexShader = R"glsl( -#version 300 es -#extension GL_OVR_multiview2 : enable - -layout(num_views=2) in; - -layout(location = 0) uniform mat4 u_MVP[2]; -layout(location = 8) uniform mat4 u_MVMatrix[2]; -layout(location = 16) uniform mat4 u_Model; -layout(location = 20) uniform vec3 u_LightPos[2]; - -layout(location = 0) in vec4 a_Position; -layout(location = 1) in vec4 a_Color; -layout(location = 2) in vec3 a_Normal; - -out vec4 v_Color; -out vec3 v_Grid; - -void main() { - mat4 mvp = u_MVP[gl_ViewID_OVR]; - mat4 modelview = u_MVMatrix[gl_ViewID_OVR]; - vec3 lightpos = u_LightPos[gl_ViewID_OVR]; - v_Grid = vec3(u_Model * a_Position); - vec3 modelViewVertex = vec3(modelview * a_Position); - vec3 modelViewNormal = vec3(modelview * vec4(a_Normal, 0.0)); - float distance = length(lightpos - modelViewVertex); - vec3 lightVector = normalize(lightpos - modelViewVertex); - float diffuse = max(dot(modelViewNormal, lightVector), 0.5); - diffuse = diffuse * (1.0 / (1.0 + (0.00001 * distance * distance))); - v_Color = vec4(a_Color.rgb * diffuse, a_Color.a); - gl_Position = mvp * a_Position; +std::array buildViewports(const std::unique_ptr &gvrapi) { + return { {gvrapi->CreateBufferViewport(), gvrapi->CreateBufferViewport()} }; } -)glsl"; + +// Computes a texture size that has approximately half as many pixels. This is +// equivalent to scaling each dimension by approximately sqrt(2)/2. +static gvr::Sizei HalfPixelCount(const gvr::Sizei &in) { + // Scale each dimension by sqrt(2)/2 ~= 7/10ths. + gvr::Sizei out; + out.width = (7 * in.width) / 10; + out.height = (7 * in.height) / 10; + return out; +} + +void testShaderBuild(const char* vs_src, const char * fs_src) { + std::string error; + GLuint vs, fs; + if (!gl::compileShader(GL_VERTEX_SHADER, vs_src, VERTEX_SHADER_DEFINES, vs, error) || + !gl::compileShader(GL_FRAGMENT_SHADER, fs_src, PIXEL_SHADER_DEFINES, fs, error)) { + throw std::runtime_error("Failed to compile shader"); + } + auto pr = gl::compileProgram({ vs, fs }, error); + if (!pr) { + throw std::runtime_error("Failed to link shader"); + } +} + #endif +static const float kZNear = 1.0f; +static const float kZFar = 100.0f; static const char *kSimepleVertexShader = R"glsl( #version 300 es @@ -147,7 +128,6 @@ void main() { } )glsl"; - static const char *kPassthroughFragmentShader = R"glsl( #version 300 es precision mediump float; @@ -327,10 +307,6 @@ namespace triangle { }}; } -std::array buildViewports(const std::unique_ptr &gvrapi) { - return { {gvrapi->CreateBufferViewport(), gvrapi->CreateBufferViewport()} }; -}; - const std::string VERTEX_SHADER_DEFINES{ R"GLSL( #version 300 es #extension GL_EXT_clip_cull_distance : enable @@ -358,44 +334,10 @@ NativeRenderer::NativeRenderer(gvr_context *vrContext) : _gvrapi(new gvr::GvrApi(vrContext, false)), _viewports(buildViewports(_gvrapi)), _gvr_viewer_type(_gvrapi->GetViewerType()) -#else -NativeRenderer::NativeRenderer(void *vrContext) -#endif { start = std::chrono::system_clock::now(); - qDebug() << "QQQ" << __FUNCTION__; } - -/** - * Converts a raw text file, saved as a resource, into an OpenGL ES shader. - * - * @param type The type of shader we will be creating. - * @param resId The resource ID of the raw text file. - * @return The shader object handler. - */ -int LoadGLShader(int type, const char *shadercode) { - GLuint result = 0; - std::string shaderError; - static const std::string SHADER_DEFINES; - if (!gl::compileShader(type, shadercode, SHADER_DEFINES, result, shaderError)) { - qWarning() << "QQQ" << __FUNCTION__ << "Shader compile failure" << shaderError.c_str(); - } - return result; -} - -// Computes a texture size that has approximately half as many pixels. This is -// equivalent to scaling each dimension by approximately sqrt(2)/2. -static gvr::Sizei HalfPixelCount(const gvr::Sizei &in) { - // Scale each dimension by sqrt(2)/2 ~= 7/10ths. - gvr::Sizei out; - out.width = (7 * in.width) / 10; - out.height = (7 * in.height) / 10; - return out; -} - - -#if defined(GVR) void NativeRenderer::InitializeVR() { _gvrapi->InitializeGl(); bool multiviewEnabled = _gvrapi->IsFeatureSupported(GVR_FEATURE_MULTIVIEW); @@ -416,6 +358,7 @@ void NativeRenderer::InitializeVR() { _swapchain.reset(new gvr::SwapChain(_gvrapi->CreateSwapChain(specs))); _viewportlist.reset(new gvr::BufferViewportList(_gvrapi->CreateEmptyBufferViewportList())); } + void NativeRenderer::PrepareFramebuffer() { const gvr::Sizei recommended_size = HalfPixelCount( _gvrapi->GetMaximumEffectiveRenderTargetSize()); @@ -429,24 +372,34 @@ void NativeRenderer::PrepareFramebuffer() { _renderSize = recommended_size; } } +#else +NativeRenderer::NativeRenderer(void *vrContext) +{ + start = std::chrono::system_clock::now(); +} #endif -void testShaderBuild(const char* vs_src, const char * fs_src) { - std::string error; - GLuint vs, fs; - if (!gl::compileShader(GL_VERTEX_SHADER, vs_src, VERTEX_SHADER_DEFINES, vs, error) || - !gl::compileShader(GL_FRAGMENT_SHADER, fs_src, PIXEL_SHADER_DEFINES, fs, error)) { - throw std::runtime_error("Failed to compile shader"); - } - auto pr = gl::compileProgram({ vs, fs }, error); - if (!pr) { - throw std::runtime_error("Failed to link shader"); + +/** + * Converts a raw text file, saved as a resource, into an OpenGL ES shader. + * + * @param type The type of shader we will be creating. + * @param resId The resource ID of the raw text file. + * @return The shader object handler. + */ +int LoadGLShader(int type, const char *shadercode) { + GLuint result = 0; + std::string shaderError; + static const std::string SHADER_DEFINES; + if (!gl::compileShader(type, shadercode, SHADER_DEFINES, result, shaderError)) { + qWarning() << "QQQ" << __FUNCTION__ << "Shader compile failure" << shaderError.c_str(); } + return result; } void NativeRenderer::InitializeGl() { qDebug() << "QQQ" << __FUNCTION__; - //gl::initModuleGl(); + #if defined(GVR) InitializeVR(); #endif @@ -456,10 +409,7 @@ void NativeRenderer::InitializeGl() { glDisable(GL_SCISSOR_TEST); glDisable(GL_BLEND); - - const uint32_t vertShader = LoadGLShader(GL_VERTEX_SHADER, kSimepleVertexShader); - //const uint32_t vertShader = LoadGLShader(GL_VERTEX_SHADER, kDiffuseLightingVertexShader); const uint32_t fragShader = LoadGLShader(GL_FRAGMENT_SHADER, kPassthroughFragmentShader); std::string error; _cubeProgram = gl::compileProgram({ vertShader, fragShader }, error); @@ -494,62 +444,8 @@ void NativeRenderer::InitializeGl() { glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); CheckGLError("build vao "); - - static std::once_flag once; - std::call_once(once, [&]{ - testShaderBuild(sdf_text3D_vert, sdf_text3D_frag); - - testShaderBuild(DrawTransformUnitQuad_vert, DrawTexture_frag); - testShaderBuild(DrawTexcoordRectTransformUnitQuad_vert, DrawTexture_frag); - testShaderBuild(DrawViewportQuadTransformTexcoord_vert, DrawTexture_frag); - testShaderBuild(DrawTransformUnitQuad_vert, DrawTextureOpaque_frag); - testShaderBuild(DrawTransformUnitQuad_vert, DrawColoredTexture_frag); - - testShaderBuild(simple_vert, simple_frag); - testShaderBuild(simple_vert, simple_textured_frag); - testShaderBuild(simple_vert, simple_textured_unlit_frag); - testShaderBuild(deferred_light_vert, directional_ambient_light_frag); - testShaderBuild(deferred_light_vert, directional_skybox_light_frag); - testShaderBuild(standardTransformPNTC_vert, standardDrawTexture_frag); - testShaderBuild(standardTransformPNTC_vert, DrawTextureOpaque_frag); - - testShaderBuild(model_vert, model_frag); - testShaderBuild(model_normal_map_vert, model_normal_map_frag); - testShaderBuild(model_vert, model_specular_map_frag); - testShaderBuild(model_normal_map_vert, model_normal_specular_map_frag); - testShaderBuild(model_vert, model_translucent_frag); - testShaderBuild(model_normal_map_vert, model_translucent_frag); - testShaderBuild(model_lightmap_vert, model_lightmap_frag); - testShaderBuild(model_lightmap_normal_map_vert, model_lightmap_normal_map_frag); - testShaderBuild(model_lightmap_vert, model_lightmap_specular_map_frag); - testShaderBuild(model_lightmap_normal_map_vert, model_lightmap_normal_specular_map_frag); - - testShaderBuild(skin_model_vert, model_frag); - testShaderBuild(skin_model_normal_map_vert, model_normal_map_frag); - testShaderBuild(skin_model_vert, model_specular_map_frag); - testShaderBuild(skin_model_normal_map_vert, model_normal_specular_map_frag); - testShaderBuild(skin_model_vert, model_translucent_frag); - testShaderBuild(skin_model_normal_map_vert, model_translucent_frag); - - testShaderBuild(model_shadow_vert, model_shadow_frag); - - testShaderBuild(overlay3D_vert, overlay3D_frag); - -#if 0 - testShaderBuild(textured_particle_vert, textured_particle_frag); - testShaderBuild(skybox_vert, skybox_frag); - testShaderBuild(paintStroke_vert,paintStroke_frag); - testShaderBuild(polyvox_vert, polyvox_frag); -#endif - - }); - - qDebug() << "done"; } -static const float kZNear = 1.0f; -static const float kZFar = 100.0f; -static const gvr_rectf fullscreen = {0, 1, 0, 1}; void NativeRenderer::DrawFrame() { auto now = std::chrono::duration_cast( @@ -559,6 +455,7 @@ void NativeRenderer::DrawFrame() { v.g = 1.0f - v.r; v.b = 1.0f; +#if defined(GVR) PrepareFramebuffer(); // A client app does its rendering here. @@ -571,6 +468,7 @@ void NativeRenderer::DrawFrame() { _head_view = toGlm(gvrHeadPose); _viewportlist->SetToRecommendedBufferViewports(); + glm::mat4 eye_views[2]; for_each_side([&](bilateral::Side side) { int eye = index(side); @@ -600,24 +498,29 @@ void NativeRenderer::DrawFrame() { glUseProgram(_cubeProgram); glBindVertexArray(_cubeVao); glDrawArrays(GL_TRIANGLES, 0, 3); - /* - float* fp; - fp = (float*)&_light_pos_eye_space[0]; - glUniform3fv(UNIFORM_LIGHT_POS, 2, fp); - fp = (float*)&_modelview_cube[0]; - glUniformMatrix4fv(UNIFORM_MV, 2, GL_FALSE, fp); - fp = (float*)&_modelview_projection_cube[0]; - glUniformMatrix4fv(UNIFORM_MVP, 2, GL_FALSE, fp); - fp = (float*)&_model_cube; - glUniformMatrix4fv(UNIFORM_M, 1, GL_FALSE, fp); - glDrawArrays(GL_TRIANGLES, 0, 36); - */ glBindVertexArray(0); }); frame.Submit(*_viewportlist, gvrHeadPose); CheckGLError("onDrawFrame"); +#else + constexpr size_t eye = 0; + const glm::mat4 eyeView{ 1 }; + const auto &mvc = _modelview_cube[eye] = eyeView * _model_cube; + const auto &mvf = _modelview_floor[eye] = eyeView * _model_floor; + const glm::mat4 perspective = glm::perspective(60.0f, 1.0f, kZNear, kZFar); + _modelview_projection_cube[eye] = perspective * mvc; + _modelview_projection_floor[eye] = perspective * mvf; + _light_pos_eye_space[eye] = glm::vec3(eyeView * _light_pos_world_space); + glClearColor(v.r, v.g, v.b, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + //glViewport(0, 0, _renderSize.width / 2, _renderSize.height); + glUseProgram(_cubeProgram); + glBindVertexArray(_cubeVao); + glDrawArrays(GL_TRIANGLES, 0, 3); + glBindVertexArray(0); +#endif } void NativeRenderer::OnTriggerEvent() { @@ -626,11 +529,15 @@ void NativeRenderer::OnTriggerEvent() { void NativeRenderer::OnPause() { qDebug() << "QQQ" << __FUNCTION__; +#if defined(GVR) _gvrapi->PauseTracking(); +#endif } void NativeRenderer::OnResume() { qDebug() << "QQQ" << __FUNCTION__; +#if defined(GVR) _gvrapi->ResumeTracking(); _gvrapi->RefreshViewerProfile(); +#endif } diff --git a/android/app/src/main/cpp/renderer.h b/android/app/src/main/cpp/renderer.h index df7c51cab4..07294f3dc1 100644 --- a/android/app/src/main/cpp/renderer.h +++ b/android/app/src/main/cpp/renderer.h @@ -4,7 +4,7 @@ #include #include -#define GVR +//#define GVR #if defined(GVR) #include diff --git a/android/app/src/main/java/org/saintandreas/testapp/MainActivity.java b/android/app/src/main/java/org/saintandreas/testapp/MainActivity.java index 7eea14dce9..783c3f4483 100644 --- a/android/app/src/main/java/org/saintandreas/testapp/MainActivity.java +++ b/android/app/src/main/java/org/saintandreas/testapp/MainActivity.java @@ -26,7 +26,7 @@ public class MainActivity extends Activity { } private long nativeRenderer; - private GvrLayout gvrLayout; + //private GvrLayout gvrLayout; private GLSurfaceView surfaceView; private native long nativeCreateRenderer(ClassLoader appClassLoader, Context context, long nativeGvrContext); @@ -55,11 +55,12 @@ public class MainActivity extends Activity { if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { setImmersiveSticky(); } }); - gvrLayout = new GvrLayout(this); + // gvrLayout = new GvrLayout(this); nativeRenderer = nativeCreateRenderer( getClass().getClassLoader(), getApplicationContext(), - gvrLayout.getGvrApi().getNativeGvrContext()); + 0); + //gvrLayout.getGvrApi().getNativeGvrContext()); surfaceView = new GLSurfaceView(this); surfaceView.setEGLContextClientVersion(3); @@ -67,18 +68,20 @@ public class MainActivity extends Activity { surfaceView.setPreserveEGLContextOnPause(true); surfaceView.setRenderer(new NativeRenderer()); - gvrLayout.setPresentationView(surfaceView); - setContentView(gvrLayout); - if (gvrLayout.setAsyncReprojectionEnabled(true)) { - AndroidCompat.setSustainedPerformanceMode(this, true); - } - AndroidCompat.setVrModeEnabled(this, true); +// gvrLayout.setPresentationView(surfaceView); +// setContentView(gvrLayout); +// if (gvrLayout.setAsyncReprojectionEnabled(true)) { +// AndroidCompat.setSustainedPerformanceMode(this, true); +// } +// AndroidCompat.setVrModeEnabled(this, true); + + setContentView(surfaceView); } @Override protected void onDestroy() { super.onDestroy(); - gvrLayout.shutdown(); + //gvrLayout.shutdown(); nativeDestroyRenderer(nativeRenderer); nativeRenderer = 0; } @@ -87,14 +90,14 @@ public class MainActivity extends Activity { protected void onPause() { surfaceView.queueEvent(()->nativeOnPause(nativeRenderer)); surfaceView.onPause(); - gvrLayout.onPause(); +// gvrLayout.onPause(); super.onPause(); } @Override protected void onResume() { super.onResume(); - gvrLayout.onResume(); +// gvrLayout.onResume(); surfaceView.onResume(); surfaceView.queueEvent(()->nativeOnResume(nativeRenderer)); } diff --git a/android/build.gradle b/android/build.gradle index 77c3dd498c..2a67707c39 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,91 +1,49 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { jcenter() + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files + classpath 'com.android.tools.build:gradle:3.0.1' } } allprojects { repositories { jcenter() + google() } } +task setupDependencies(type: Copy) { + from HIFI_ANDROID_PRECOMPILED + '/jni/arm64-v8a' + into 'app/src/main/jniLibs/arm64-v8a' +} + +apply from: 'setupQt.gradle' +setupDependencies.dependsOn setupQt + +apply from: 'setupScribe.gradle' +setupDependencies.dependsOn setupScribe + +apply from: 'setupOpenSSL.gradle' +setupDependencies.dependsOn setupOpenSSL + +apply from: 'setupTBB.gradle' +setupDependencies.dependsOn setupTBB + +apply from: 'setupGVR.gradle' +setupDependencies.dependsOn setupGVR + +task copyDependencies(type: Copy) { + from HIFI_ANDROID_PRECOMPILED + '/jni/arm64-v8a' + into 'app/src/main/jniLibs/arm64-v8a' +} + +task cleanDependencies(type: Delete) { + delete HIFI_ANDROID_PRECOMPILED +} + task clean(type: Delete) { delete rootProject.buildDir } - -task extractQt5jars(type: Copy) { - from fileTree(QT5_ROOT + "/jar") - into("${project.rootDir}/libraries/jar") - include("*.jar") -} - -task extractQt5so(type: Copy) { - from fileTree(QT5_ROOT + "/lib") - into("${project.rootDir}/libraries/jni/armeabi-v7a/") - include("libQt5AndroidExtras.so") - include("libQt5Concurrent.so") - include("libQt5Core.so") - include("libQt5Gamepad.so") - include("libQt5Gui.so") - include("libQt5Location.so") - include("libQt5Multimedia.so") - include("libQt5MultimediaQuick_p.so") - include("libQt5Network.so") - include("libQt5NetworkAuth.so") - include("libQt5OpenGL.so") - include("libQt5Positioning.so") - include("libQt5Qml.so") - include("libQt5Quick.so") - include("libQt5QuickControls2.so") - include("libQt5QuickParticles.so") - include("libQt5QuickTemplates2.so") - include("libQt5QuickWidgets.so") - include("libQt5Script.so") - include("libQt5ScriptTools.so") - include("libQt5Sensors.so") - include("libQt5Svg.so") - include("libQt5WebChannel.so") - include("libQt5WebSockets.so") - include("libQt5WebView.so") - include("libQt5Widgets.so") - include("libQt5Xml.so") - include("libQt5XmlPatterns.so") -} - -task extractAudioSo(type: Copy) { - from zipTree(GVR_ROOT + "/libraries/sdk-audio-1.80.0.aar") - into "${project.rootDir}/libraries/" - include "jni/armeabi-v7a/libgvr_audio.so" -} - -task extractGvrSo(type: Copy) { - from zipTree(GVR_ROOT + "/libraries/sdk-base-1.80.0.aar") - into "${project.rootDir}/libraries/" - include "jni/armeabi-v7a/libgvr.so" -} - -task extractNdk { } -extractNdk.dependsOn extractAudioSo -extractNdk.dependsOn extractGvrSo - -task extractQt5 { } -extractQt5.dependsOn extractQt5so -extractQt5.dependsOn extractQt5jars - -task extractBinaries { } -extractBinaries.dependsOn extractQt5 -extractBinaries.dependsOn extractNdk - -task deleteBinaries(type: Delete) { - delete "${project.rootDir}/libraries/jni" -} - -//clean.dependsOn(deleteBinaries) diff --git a/android/setupGVR.gradle b/android/setupGVR.gradle new file mode 100644 index 0000000000..3fe86498aa --- /dev/null +++ b/android/setupGVR.gradle @@ -0,0 +1,41 @@ +buildscript { + repositories { + jcenter() + google() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.0.1' + classpath 'de.undercouch:gradle-download-task:3.3.0' + } +} + + +def file='gvrsdk_v1.101.0.tgz' +def url='https://github.com/googlevr/gvr-android-sdk/archive/v1.101.0.tar.gz' +def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) + +// FIXME find a way to only download if the file doesn't exist +task downloadGVR(type: de.undercouch.gradle.tasks.download.Download) { + src url + dest destFile +} + +task extractGVR(dependsOn: downloadGVR, type: Copy) { + from tarTree(resources.gzip(destFile)) + into new File(HIFI_ANDROID_PRECOMPILED, 'gvr') +} + +task copyGVRAudioLibs(dependsOn: extractGVR, type: Copy) { + from zipTree(new File(HIFI_ANDROID_PRECOMPILED, 'gvr/gvr-android-sdk-1.101.0/libraries/sdk-audio-1.101.0.aar')) + include 'jni/arm64-v8a/libgvr_audio.so' + into HIFI_ANDROID_PRECOMPILED +} + +task copyGVRLibs(dependsOn: extractGVR, type: Copy) { + from zipTree(new File(HIFI_ANDROID_PRECOMPILED, 'gvr/gvr-android-sdk-1.101.0/libraries/sdk-base-1.101.0.aar')) + include 'jni/arm64-v8a/libgvr.so' + into HIFI_ANDROID_PRECOMPILED +} + +task setupGVR(dependsOn: [copyGVRLibs, copyGVRAudioLibs]) { +} diff --git a/android/setupOpenSSL.gradle b/android/setupOpenSSL.gradle new file mode 100644 index 0000000000..8001b71f3a --- /dev/null +++ b/android/setupOpenSSL.gradle @@ -0,0 +1,26 @@ +buildscript { + repositories { + jcenter() + google() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.0.1' + classpath 'de.undercouch:gradle-download-task:3.3.0' + } +} + +def file='openssl-1.1.0g_armv8.tgz' +def url='https://s3.amazonaws.com/Oculus/Android/' + file +def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) + +task downloadOpenSSL(type: de.undercouch.gradle.tasks.download.Download) { + src url + dest destFile +} + +task extractOpenSSL(dependsOn: downloadOpenSSL, type: Copy) { + from tarTree(resources.gzip(destFile)) + into new File(HIFI_ANDROID_PRECOMPILED, 'openssl') +} + +task setupOpenSSL(dependsOn: extractOpenSSL) { } diff --git a/android/setupQt.gradle b/android/setupQt.gradle new file mode 100644 index 0000000000..84e4715ce8 --- /dev/null +++ b/android/setupQt.gradle @@ -0,0 +1,63 @@ +buildscript { + repositories { + jcenter() + google() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.0.1' + classpath 'de.undercouch:gradle-download-task:3.3.0' + } +} + +def file='qt-5.9.2_armv8-libcpp.tgz' +def url='https://s3.amazonaws.com/Oculus/Android/' + file +def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) + +task downloadQt(type: de.undercouch.gradle.tasks.download.Download) { + src url + dest destFile +} + +task extractQt(dependsOn: downloadQt, type: Copy) { + from tarTree(resources.gzip(destFile)) + into new File(HIFI_ANDROID_PRECOMPILED, 'qt') +} + +task copyQtJars(dependsOn: extractQt, type: Copy) { + from 'build/qt/jar' + include '*.jar' + into HIFI_ANDROID_PRECOMPILED + '/jar' +} + +task copyQtLibs(dependsOn: extractQt, type: Copy) { + from 'build/qt/lib' + include 'libQt5AndroidExtras.so' + include 'libQt5Concurrent.so' + include 'libQt5Core.so' + include 'libQt5Gamepad.so' + include 'libQt5Gui.so' + include 'libQt5MultimediaQuick_p.so' + include 'libQt5Multimedia.so' + include 'libQt5Network.so' + include 'libQt5OpenGL.so' + include 'libQt5Qml.so' + include 'libQt5QuickControls2.so' + include 'libQt5QuickParticles.so' + include 'libQt5Quick.so' + include 'libQt5QuickTemplates2.so' + include 'libQt5QuickWidgets.so' + include 'libQt5Script.so' + include 'libQt5ScriptTools.so' + include 'libQt5Scxml.so' + include 'libQt5Svg.so' + include 'libQt5WebChannel.so' + include 'libQt5WebSockets.so' + include 'libQt5WebView.so' + include 'libQt5Widgets.so' + include 'libQt5XmlPatterns.so' + include 'libQt5Xml.so' + into HIFI_ANDROID_PRECOMPILED + '/jni/arm64-v8a' +} + +task setupQt(dependsOn: [copyQtLibs, copyQtJars]) { +} diff --git a/android/setupScribe.gradle b/android/setupScribe.gradle new file mode 100644 index 0000000000..40ffff5ceb --- /dev/null +++ b/android/setupScribe.gradle @@ -0,0 +1,27 @@ +buildscript { + repositories { + jcenter() + google() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.0.1' + classpath 'de.undercouch:gradle-download-task:3.3.0' + } +} + +def file='scribe_linux_x86_64' +def url='https://s3.amazonaws.com/Oculus/Android/' + file +def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) + +task filepermission(type: Exec) { + commandLine 'chmod', '700', '' +} + +task downloadScribe(type: de.undercouch.gradle.tasks.download.Download) { + src url + dest destFile +} + +task setupScribe(dependsOn: downloadScribe, type: Exec) { + commandLine 'chmod', 'a+x', destFile +} diff --git a/android/setupTBB.gradle b/android/setupTBB.gradle new file mode 100644 index 0000000000..89bba79a87 --- /dev/null +++ b/android/setupTBB.gradle @@ -0,0 +1,31 @@ +buildscript { + repositories { + jcenter() + google() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.0.1' + classpath 'de.undercouch:gradle-download-task:3.3.0' + } +} + +def file='tbb-2018_U1_armv8_libcpp.tgz' +def url='https://s3.amazonaws.com/Oculus/Android/' + file +def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) + +task downloadTBB(type: de.undercouch.gradle.tasks.download.Download) { + src url + dest destFile +} + +task extractTBB(dependsOn: downloadTBB, type: Copy) { + from tarTree(resources.gzip(destFile)) + into new File(HIFI_ANDROID_PRECOMPILED, 'tbb') +} + +task setupTBB(dependsOn: extractTBB, type: Copy) { + from 'build/tbb/lib/release' + include 'libtbb.so' + include 'libtbbmalloc.so' + into HIFI_ANDROID_PRECOMPILED + '/jni/arm64-v8a/' +} diff --git a/cmake/macros/TargetOpenSSL.cmake b/cmake/macros/TargetOpenSSL.cmake index 7ee0283a48..82601bf6aa 100644 --- a/cmake/macros/TargetOpenSSL.cmake +++ b/cmake/macros/TargetOpenSSL.cmake @@ -6,14 +6,10 @@ # See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html # macro(TARGET_OPENSSL) - if (ANDROID) - - # FIXME use a distributable binary - set(OPENSSL_INSTALL_DIR C:/Android/openssl) + set(OPENSSL_INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/openssl) set(OPENSSL_INCLUDE_DIR "${OPENSSL_INSTALL_DIR}/include" CACHE TYPE INTERNAL) set(OPENSSL_LIBRARIES "${OPENSSL_INSTALL_DIR}/lib/libcrypto.a;${OPENSSL_INSTALL_DIR}/lib/libssl.a" CACHE TYPE INTERNAL) - else() find_package(OpenSSL REQUIRED) @@ -28,5 +24,4 @@ macro(TARGET_OPENSSL) include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") target_link_libraries(${TARGET_NAME} ${OPENSSL_LIBRARIES}) - endmacro() diff --git a/cmake/macros/TargetTBB.cmake b/cmake/macros/TargetTBB.cmake index e9c4639c3d..1e2e69eeaa 100644 --- a/cmake/macros/TargetTBB.cmake +++ b/cmake/macros/TargetTBB.cmake @@ -8,10 +8,10 @@ macro(TARGET_TBB) if (ANDROID) - set(TBB_INSTALL_DIR C:/tbb-2018/built) - set(TBB_LIBRARY ${HIFI_ANDROID_PRECOMPILED}/libtbb.so CACHE FILEPATH "TBB library location") - set(TBB_MALLOC_LIBRARY ${HIFI_ANDROID_PRECOMPILED}/libtbbmalloc.so CACHE FILEPATH "TBB malloc library location") - set(TBB_INCLUDE_DIRS ${TBB_INSTALL_DIR}/include CACHE TYPE "List of tbb include directories" CACHE FILEPATH "TBB includes location") + set(TBB_INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/tbb) + set(TBB_INCLUDE_DIRS ${TBB_INSTALL_DIR}/include CACHE FILEPATH "TBB includes location") + set(TBB_LIBRARY ${TBB_INSTALL_DIR}/lib/release/libtbb.so CACHE FILEPATH "TBB library location") + set(TBB_MALLOC_LIBRARY ${TBB_INSTALL_DIR}/lib/release/libtbbmalloc.so CACHE FILEPATH "TBB malloc library location") set(TBB_LIBRARIES ${TBB_LIBRARY} ${TBB_MALLOC_LIBRARY}) else() add_dependency_external_projects(tbb) diff --git a/libraries/networking/src/AssetUtils.cpp b/libraries/networking/src/AssetUtils.cpp index 3af0b1df47..76fda6aed4 100644 --- a/libraries/networking/src/AssetUtils.cpp +++ b/libraries/networking/src/AssetUtils.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include "NetworkAccessManager.h" diff --git a/libraries/networking/src/DataServerAccountInfo.cpp b/libraries/networking/src/DataServerAccountInfo.cpp index 6c6f3eb90c..51f93d13b0 100644 --- a/libraries/networking/src/DataServerAccountInfo.cpp +++ b/libraries/networking/src/DataServerAccountInfo.cpp @@ -12,9 +12,10 @@ #include #include -#include +#include #include #include +#include #include diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 1e682f367a..94bc4eeff6 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include From 6bdaf638cfd24fb1990d273061140c27bb905dcf Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 21 Nov 2017 22:25:29 -0800 Subject: [PATCH 11/30] Support OSX build --- android/app/build.gradle | 2 +- android/setupQt.gradle | 6 ++++++ android/setupScribe.gradle | 12 +++++++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 30b0bf78b4..18eb91bceb 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -17,7 +17,7 @@ android { '-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=c++_shared', '-DQT_CMAKE_PREFIX_PATH=' + HIFI_ANDROID_PRECOMPILED + '/qt/lib/cmake', - '-DNATIVE_SCRIBE=' + HIFI_ANDROID_PRECOMPILED + '/scribe_linux_x86_64', + '-DNATIVE_SCRIBE=' + HIFI_ANDROID_PRECOMPILED + '/scribe', '-DHIFI_ANDROID_PRECOMPILED=' + HIFI_ANDROID_PRECOMPILED } } diff --git a/android/setupQt.gradle b/android/setupQt.gradle index 84e4715ce8..6c4ce8ab6c 100644 --- a/android/setupQt.gradle +++ b/android/setupQt.gradle @@ -9,7 +9,13 @@ buildscript { } } + +import org.apache.tools.ant.taskdefs.condition.Os + def file='qt-5.9.2_armv8-libcpp.tgz' +if (Os.isFamily(Os.FAMILY_MAC)) { + file = 'qt-5.9.2_osx_armv8-libcpp.tgz' +} def url='https://s3.amazonaws.com/Oculus/Android/' + file def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) diff --git a/android/setupScribe.gradle b/android/setupScribe.gradle index 40ffff5ceb..7456e5eca1 100644 --- a/android/setupScribe.gradle +++ b/android/setupScribe.gradle @@ -9,9 +9,19 @@ buildscript { } } +import org.apache.tools.ant.taskdefs.condition.Os + def file='scribe_linux_x86_64' +if (Os.isFamily(Os.FAMILY_MAC)) { + file = 'scribe_osx_x86_64' +} +def localFile='scribe' +if (Os.isFamily(Os.FAMILY_WINDOWS)) { + file = 'scribe.exe' +} + def url='https://s3.amazonaws.com/Oculus/Android/' + file -def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) +def destFile = new File(HIFI_ANDROID_PRECOMPILED, localFile) task filepermission(type: Exec) { commandLine 'chmod', '700', '' From 8f43083deda140438bfee81e717d1a48b0175991 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 22 Nov 2017 17:15:45 -0800 Subject: [PATCH 12/30] Enable windows builds --- android/setupGVR.gradle | 2 +- android/setupOpenSSL.gradle | 2 +- android/setupQt.gradle | 7 +++++-- android/setupScribe.gradle | 14 ++++++++------ android/setupTBB.gradle | 2 +- 5 files changed, 16 insertions(+), 11 deletions(-) diff --git a/android/setupGVR.gradle b/android/setupGVR.gradle index 3fe86498aa..c91674068f 100644 --- a/android/setupGVR.gradle +++ b/android/setupGVR.gradle @@ -11,7 +11,7 @@ buildscript { def file='gvrsdk_v1.101.0.tgz' -def url='https://github.com/googlevr/gvr-android-sdk/archive/v1.101.0.tar.gz' +def url='https://hifi-public.s3.amazonaws.com/austin/android/' + file def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) // FIXME find a way to only download if the file doesn't exist diff --git a/android/setupOpenSSL.gradle b/android/setupOpenSSL.gradle index 8001b71f3a..2a76405dda 100644 --- a/android/setupOpenSSL.gradle +++ b/android/setupOpenSSL.gradle @@ -10,7 +10,7 @@ buildscript { } def file='openssl-1.1.0g_armv8.tgz' -def url='https://s3.amazonaws.com/Oculus/Android/' + file +def url='https://hifi-public.s3.amazonaws.com/austin/android/' + file def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) task downloadOpenSSL(type: de.undercouch.gradle.tasks.download.Download) { diff --git a/android/setupQt.gradle b/android/setupQt.gradle index 6c4ce8ab6c..541fe5c44d 100644 --- a/android/setupQt.gradle +++ b/android/setupQt.gradle @@ -12,11 +12,14 @@ buildscript { import org.apache.tools.ant.taskdefs.condition.Os -def file='qt-5.9.2_armv8-libcpp.tgz' +def file='qt-5.9.2_linux_armv8-libcpp.tgz' if (Os.isFamily(Os.FAMILY_MAC)) { file = 'qt-5.9.2_osx_armv8-libcpp.tgz' +} else if (Os.isFamily(Os.FAMILY_WINDOWS)) { + file = 'qt-5.9.3_win_armv8-libcpp.tgz' } -def url='https://s3.amazonaws.com/Oculus/Android/' + file + +def url='https://hifi-public.s3.amazonaws.com/austin/android/' + file def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) task downloadQt(type: de.undercouch.gradle.tasks.download.Download) { diff --git a/android/setupScribe.gradle b/android/setupScribe.gradle index 7456e5eca1..b415715309 100644 --- a/android/setupScribe.gradle +++ b/android/setupScribe.gradle @@ -12,19 +12,21 @@ buildscript { import org.apache.tools.ant.taskdefs.condition.Os def file='scribe_linux_x86_64' +def localFile='scribe' if (Os.isFamily(Os.FAMILY_MAC)) { file = 'scribe_osx_x86_64' -} -def localFile='scribe' -if (Os.isFamily(Os.FAMILY_WINDOWS)) { - file = 'scribe.exe' +} else if (Os.isFamily(Os.FAMILY_WINDOWS)) { + file = 'scribe_win32_x86_64.exe' + localFile = 'scribe.exe' } -def url='https://s3.amazonaws.com/Oculus/Android/' + file +def url='https://hifi-public.s3.amazonaws.com/austin/android/' + file def destFile = new File(HIFI_ANDROID_PRECOMPILED, localFile) task filepermission(type: Exec) { - commandLine 'chmod', '700', '' + if (!Os.isFamily(Os.FAMILY_WINDOWS)) { + commandLine 'chmod', '700', '' + } } task downloadScribe(type: de.undercouch.gradle.tasks.download.Download) { diff --git a/android/setupTBB.gradle b/android/setupTBB.gradle index 89bba79a87..b90e163268 100644 --- a/android/setupTBB.gradle +++ b/android/setupTBB.gradle @@ -10,7 +10,7 @@ buildscript { } def file='tbb-2018_U1_armv8_libcpp.tgz' -def url='https://s3.amazonaws.com/Oculus/Android/' + file +def url='https://hifi-public.s3.amazonaws.com/austin/android/' + file def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) task downloadTBB(type: de.undercouch.gradle.tasks.download.Download) { From e086bed021e4ffc713878c34358547d1d2d8f263 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 23 Nov 2017 09:13:15 -0800 Subject: [PATCH 13/30] Updating OSX to Qt 5.9.3 --- android/setupQt.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/setupQt.gradle b/android/setupQt.gradle index 541fe5c44d..fc2af24fd1 100644 --- a/android/setupQt.gradle +++ b/android/setupQt.gradle @@ -14,7 +14,7 @@ import org.apache.tools.ant.taskdefs.condition.Os def file='qt-5.9.2_linux_armv8-libcpp.tgz' if (Os.isFamily(Os.FAMILY_MAC)) { - file = 'qt-5.9.2_osx_armv8-libcpp.tgz' + file = 'qt-5.9.3_osx_armv8-libcpp.tgz' } else if (Os.isFamily(Os.FAMILY_WINDOWS)) { file = 'qt-5.9.3_win_armv8-libcpp.tgz' } From 113844384a41ad24edc497defeaea5455bd1c9ec Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Thu, 23 Nov 2017 10:31:15 -0800 Subject: [PATCH 14/30] Update linux android Qt to 5.9.3 --- android/setupQt.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/setupQt.gradle b/android/setupQt.gradle index fc2af24fd1..32626d3605 100644 --- a/android/setupQt.gradle +++ b/android/setupQt.gradle @@ -12,7 +12,7 @@ buildscript { import org.apache.tools.ant.taskdefs.condition.Os -def file='qt-5.9.2_linux_armv8-libcpp.tgz' +def file='qt-5.9.3_linux_armv8-libcpp.tgz' if (Os.isFamily(Os.FAMILY_MAC)) { file = 'qt-5.9.3_osx_armv8-libcpp.tgz' } else if (Os.isFamily(Os.FAMILY_WINDOWS)) { From d6072f2bf2c451069339f9c5f6ea504d76569843 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Fri, 24 Nov 2017 14:10:07 -0800 Subject: [PATCH 15/30] Add bullet and draco to precompiled libraries --- android/app/CMakeLists.txt | 14 +++++++++- android/app/build.gradle | 1 - android/build.gradle | 6 +++++ android/setupBullet.gradle | 26 +++++++++++++++++++ android/setupDraco.gradle | 26 +++++++++++++++++++ cmake/macros/TargetBullet.cmake | 17 ++++++++++-- cmake/macros/TargetDraco.cmake | 18 +++++++++++++ libraries/fbx/CMakeLists.txt | 5 +--- libraries/image/src/image/Image.cpp | 22 +++++++++------- .../procedural/src/procedural/Procedural.cpp | 1 + .../render-utils/src/DebugDeferredBuffer.cpp | 3 ++- 11 files changed, 121 insertions(+), 18 deletions(-) create mode 100644 android/setupBullet.gradle create mode 100644 android/setupDraco.gradle create mode 100755 cmake/macros/TargetDraco.cmake diff --git a/android/app/CMakeLists.txt b/android/app/CMakeLists.txt index 65709f7547..74957583a1 100644 --- a/android/app/CMakeLists.txt +++ b/android/app/CMakeLists.txt @@ -1,8 +1,20 @@ set(TARGET_NAME native-lib) setup_hifi_library() -link_hifi_libraries(shared networking gl gpu gpu-gles) +link_hifi_libraries(shared networking gl gpu gpu-gles image fbx render-utils physics) target_opengl() target_link_libraries(native-lib android log m) set(GVR_ROOT "${HIFI_ANDROID_PRECOMPILED}/gvr/gvr-android-sdk-1.101.0/") target_include_directories(native-lib PRIVATE "${GVR_ROOT}/libraries/headers") target_link_libraries(native-lib "${HIFI_ANDROID_PRECOMPILED}/jni/arm64-v8a/libgvr.so") + +# finished libraries +# core -> qt +# networking -> openssl, tbb +# fbx -> draco +# physics -> bullet + +# unfinished libraries +# image -> nvtt (doesn't look good, but can be made optional) +# script-engine -> quazip (probably not required for the android client) +# entities-renderer -> polyvox + diff --git a/android/app/build.gradle b/android/app/build.gradle index 18eb91bceb..005ec1a3ad 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,4 +1,3 @@ - apply plugin: 'com.android.application' android { diff --git a/android/build.gradle b/android/build.gradle index 2a67707c39..e2546e524f 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -35,6 +35,12 @@ setupDependencies.dependsOn setupTBB apply from: 'setupGVR.gradle' setupDependencies.dependsOn setupGVR +apply from: 'setupDraco.gradle' +setupDependencies.dependsOn setupDraco + +apply from: 'setupBullet.gradle' +setupDependencies.dependsOn setupBullet + task copyDependencies(type: Copy) { from HIFI_ANDROID_PRECOMPILED + '/jni/arm64-v8a' into 'app/src/main/jniLibs/arm64-v8a' diff --git a/android/setupBullet.gradle b/android/setupBullet.gradle new file mode 100644 index 0000000000..5fb1bd4369 --- /dev/null +++ b/android/setupBullet.gradle @@ -0,0 +1,26 @@ +buildscript { + repositories { + jcenter() + google() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.0.1' + classpath 'de.undercouch:gradle-download-task:3.3.0' + } +} + +def file='bullet-2.83_armv8-libcpp.tgz ' +def url='https://hifi-public.s3.amazonaws.com/austin/android/' + file +def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) + +task downloadBullet(type: de.undercouch.gradle.tasks.download.Download) { + src url + dest destFile +} + +task extractBullet(dependsOn: downloadBullet, type: Copy) { + from tarTree(resources.gzip(destFile)) + into new File(HIFI_ANDROID_PRECOMPILED, 'bullet') +} + +task setupBullet(dependsOn: extractBullet) { } diff --git a/android/setupDraco.gradle b/android/setupDraco.gradle new file mode 100644 index 0000000000..cae24b8a0f --- /dev/null +++ b/android/setupDraco.gradle @@ -0,0 +1,26 @@ +buildscript { + repositories { + jcenter() + google() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.0.1' + classpath 'de.undercouch:gradle-download-task:3.3.0' + } +} + +def file='draco_armv8-libcpp.tgz' +def url='https://hifi-public.s3.amazonaws.com/austin/android/' + file +def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) + +task downloadDraco(type: de.undercouch.gradle.tasks.download.Download) { + src url + dest destFile +} + +task extractDraco(dependsOn: downloadDraco, type: Copy) { + from tarTree(resources.gzip(destFile)) + into new File(HIFI_ANDROID_PRECOMPILED, 'draco') +} + +task setupDraco(dependsOn: extractDraco) { } diff --git a/cmake/macros/TargetBullet.cmake b/cmake/macros/TargetBullet.cmake index 207595d23f..48fe0e0c05 100644 --- a/cmake/macros/TargetBullet.cmake +++ b/cmake/macros/TargetBullet.cmake @@ -6,8 +6,19 @@ # See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html # macro(TARGET_BULLET) - add_dependency_external_projects(bullet) - find_package(Bullet REQUIRED) + if (ANDROID) + set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/bullet) + set(BULLET_INCLUDE_DIRS "${INSTALL_DIR}/include/bullet" CACHE TYPE INTERNAL) + + set(LIB_DIR ${INSTALL_DIR}/lib) + list(APPEND BULLET_LIBRARIES ${LIB_DIR}/libBulletDynamics.a) + list(APPEND BULLET_LIBRARIES ${LIB_DIR}/libBulletCollision.a) + list(APPEND BULLET_LIBRARIES ${LIB_DIR}/libLinearMath.a) + list(APPEND BULLET_LIBRARIES ${LIB_DIR}/libBulletSoftBody.a) + else() + add_dependency_external_projects(bullet) + find_package(Bullet REQUIRED) + endif() # perform the system include hack for OS X to ignore warnings if (APPLE) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem ${BULLET_INCLUDE_DIRS}") @@ -16,3 +27,5 @@ macro(TARGET_BULLET) endif() target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES}) endmacro() + + diff --git a/cmake/macros/TargetDraco.cmake b/cmake/macros/TargetDraco.cmake new file mode 100755 index 0000000000..c198ac35b0 --- /dev/null +++ b/cmake/macros/TargetDraco.cmake @@ -0,0 +1,18 @@ +macro(TARGET_DRACO) + if (ANDROID) + set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/draco) + set(DRACO_INCLUDE_DIRS "${INSTALL_DIR}/include" CACHE TYPE INTERNAL) + + set(LIB_DIR ${INSTALL_DIR}/lib) + list(APPEND DRACO_LIBRARIES ${LIB_DIR}/libdraco.a) + list(APPEND DRACO_LIBRARIES ${LIB_DIR}/libdracodec.a) + list(APPEND DRACO_LIBRARIES ${LIB_DIR}/libdracoenc.a) + else() + add_dependency_external_projects(draco) + find_package(Draco REQUIRED) + list(APPEND DRACO_LIBRARIES ${DRACO_LIBRARY}) + list(APPEND DRACO_LIBRARIES ${DRACO_ENCODER_LIBRARY}) + endif() + target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${DRACO_INCLUDE_DIRS}) + target_link_libraries(${TARGET_NAME} ${DRACO_LIBRARIES}) +endmacro() diff --git a/libraries/fbx/CMakeLists.txt b/libraries/fbx/CMakeLists.txt index 7cead5aa4f..683ddb52f7 100644 --- a/libraries/fbx/CMakeLists.txt +++ b/libraries/fbx/CMakeLists.txt @@ -4,7 +4,4 @@ setup_hifi_library() link_hifi_libraries(shared model networking image) include_hifi_library_headers(gpu image) -add_dependency_external_projects(draco) -find_package(Draco REQUIRED) -target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${DRACO_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${DRACO_LIBRARY} ${DRACO_ENCODER_LIBRARY}) +target_draco() diff --git a/libraries/image/src/image/Image.cpp b/libraries/image/src/image/Image.cpp index 5959714cd8..9f584c844f 100644 --- a/libraries/image/src/image/Image.cpp +++ b/libraries/image/src/image/Image.cpp @@ -11,7 +11,6 @@ #include "Image.h" -#include #include #include @@ -20,6 +19,15 @@ #include #include + +#if defined(Q_OS_ANDROID) +#define CPU_MIPMAPS 0 +#else +#define CPU_MIPMAPS 1 +#include +#endif + + #include #include #include @@ -29,13 +37,6 @@ using namespace gpu; -#if defined(Q_OS_ANDROID) -#define CPU_MIPMAPS 0 -#else -#define CPU_MIPMAPS 1 -#include -#endif - static const glm::uvec2 SPARSE_PAGE_SIZE(128); static const glm::uvec2 MAX_TEXTURE_SIZE(4096); @@ -410,7 +411,6 @@ struct MyErrorHandler : public nvtt::ErrorHandler { qCWarning(imagelogging) << "Texture compression error:" << nvtt::errorString(e); } }; -#endif class SequentialTaskDispatcher : public nvtt::TaskDispatcher { public: @@ -637,6 +637,10 @@ void generateLDRMips(gpu::Texture* texture, QImage& image, const std::atomic& abortProcessing = false, int face = -1) { #if CPU_MIPMAPS PROFILE_RANGE(resource_parse, "generateMips"); diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index 69e9768ccd..7b718515a8 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index d334a53fa1..02a5496151 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -11,7 +11,8 @@ #include "DebugDeferredBuffer.h" -#include +#include +#include #include #include From ddc2548c537504be089fed2bc5933e985a2e708e Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Fri, 24 Nov 2017 15:12:29 -0800 Subject: [PATCH 16/30] Add polyvox, fix task copy bugs --- android/app/CMakeLists.txt | 3 ++- android/build.gradle | 3 +++ android/setupPolyvox.gradle | 38 ++++++++++++++++++++++++++++++++ android/setupQt.gradle | 4 ++-- android/setupTBB.gradle | 2 +- cmake/macros/TargetPolyvox.cmake | 24 ++++++++++++++++++++ 6 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 android/setupPolyvox.gradle create mode 100644 cmake/macros/TargetPolyvox.cmake diff --git a/android/app/CMakeLists.txt b/android/app/CMakeLists.txt index 74957583a1..2451a8804c 100644 --- a/android/app/CMakeLists.txt +++ b/android/app/CMakeLists.txt @@ -12,9 +12,10 @@ target_link_libraries(native-lib "${HIFI_ANDROID_PRECOMPILED}/jni/arm64-v8a/libg # networking -> openssl, tbb # fbx -> draco # physics -> bullet +# entities-renderer -> polyvox # unfinished libraries # image -> nvtt (doesn't look good, but can be made optional) # script-engine -> quazip (probably not required for the android client) -# entities-renderer -> polyvox + diff --git a/android/build.gradle b/android/build.gradle index e2546e524f..43cdb0e8ac 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -41,6 +41,9 @@ setupDependencies.dependsOn setupDraco apply from: 'setupBullet.gradle' setupDependencies.dependsOn setupBullet +apply from: 'setupPolyvox.gradle' +setupDependencies.dependsOn setupPolyvox + task copyDependencies(type: Copy) { from HIFI_ANDROID_PRECOMPILED + '/jni/arm64-v8a' into 'app/src/main/jniLibs/arm64-v8a' diff --git a/android/setupPolyvox.gradle b/android/setupPolyvox.gradle new file mode 100644 index 0000000000..168fbd9b15 --- /dev/null +++ b/android/setupPolyvox.gradle @@ -0,0 +1,38 @@ +buildscript { + repositories { + jcenter() + google() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.0.1' + classpath 'de.undercouch:gradle-download-task:3.3.0' + } +} + +def file='polyvox_armv8-libcpp.tgz' +def url='https://hifi-public.s3.amazonaws.com/austin/android/' + file +def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) + +task downloadPolyvox(type: de.undercouch.gradle.tasks.download.Download) { + src url + dest destFile +} + +task extractPolyvox(dependsOn: downloadPolyvox, type: Copy) { + from tarTree(resources.gzip(destFile)) + into new File(HIFI_ANDROID_PRECOMPILED, 'polyvox') +} + +task copyPolyvoxCore(dependsOn: extractPolyvox, type: Copy) { + from HIFI_ANDROID_PRECOMPILED + '/polyvox/lib/Release' + include 'libPolyVoxCore.so' + into HIFI_ANDROID_PRECOMPILED + '/jni/arm64-v8a' +} + +task copyPolyvoxUtil(dependsOn: extractPolyvox, type: Copy) { + from HIFI_ANDROID_PRECOMPILED + '/polyvox/lib' + include 'libPolyVoxUtil.so' + into HIFI_ANDROID_PRECOMPILED + '/jni/arm64-v8a' +} + +task setupPolyvox(dependsOn: [copyPolyvoxCore, copyPolyvoxUtil]) { } diff --git a/android/setupQt.gradle b/android/setupQt.gradle index 32626d3605..32a87d9580 100644 --- a/android/setupQt.gradle +++ b/android/setupQt.gradle @@ -33,13 +33,13 @@ task extractQt(dependsOn: downloadQt, type: Copy) { } task copyQtJars(dependsOn: extractQt, type: Copy) { - from 'build/qt/jar' + from HIFI_ANDROID_PRECOMPILED + '/qt/jar' include '*.jar' into HIFI_ANDROID_PRECOMPILED + '/jar' } task copyQtLibs(dependsOn: extractQt, type: Copy) { - from 'build/qt/lib' + from HIFI_ANDROID_PRECOMPILED + '/qt/lib' include 'libQt5AndroidExtras.so' include 'libQt5Concurrent.so' include 'libQt5Core.so' diff --git a/android/setupTBB.gradle b/android/setupTBB.gradle index b90e163268..55d7a9164e 100644 --- a/android/setupTBB.gradle +++ b/android/setupTBB.gradle @@ -24,7 +24,7 @@ task extractTBB(dependsOn: downloadTBB, type: Copy) { } task setupTBB(dependsOn: extractTBB, type: Copy) { - from 'build/tbb/lib/release' + from HIFI_ANDROID_PRECOMPILED + '/tbb/lib/release' include 'libtbb.so' include 'libtbbmalloc.so' into HIFI_ANDROID_PRECOMPILED + '/jni/arm64-v8a/' diff --git a/cmake/macros/TargetPolyvox.cmake b/cmake/macros/TargetPolyvox.cmake new file mode 100644 index 0000000000..f03a1ec42f --- /dev/null +++ b/cmake/macros/TargetPolyvox.cmake @@ -0,0 +1,24 @@ +# +# Copyright 2015 High Fidelity, Inc. +# Created by Bradley Austin Davis on 2015/10/10 +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# +macro(TARGET_POLYVOX) + if (ANDROID) + set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/polyvox) + set(POLYVOX_INCLUDE_DIRS "${INSTALL_DIR}/include" CACHE TYPE INTERNAL) + set(LIB_DIR ${INSTALL_DIR}/lib) + list(APPEND POLYVOX_LIBRARIES ${LIB_DIR}/libPolyVoxUtil.so) + list(APPEND POLYVOX_LIBRARIES ${LIB_DIR}/Release/libPolyVoxCore.so) + else() + add_dependency_external_projects(polyvox) + find_package(PolyVox REQUIRED) + endif() + target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${POLYVOX_INCLUDE_DIRS}) + target_link_libraries(${TARGET_NAME} ${POLYVOX_LIBRARIES}) +endmacro() + + + From 92933912976dd68c7ebe47cd6b2a674163943749 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Sun, 26 Nov 2017 18:31:25 -0800 Subject: [PATCH 17/30] Reduce number of gradle files --- android/app/CMakeLists.txt | 3 +- android/build.gradle | 136 +++++++++++++++++++++++++++++------- android/setupBullet.gradle | 26 ------- android/setupDraco.gradle | 26 ------- android/setupOpenSSL.gradle | 26 ------- android/setupPolyvox.gradle | 38 ---------- android/setupQt.gradle | 72 ------------------- android/setupScribe.gradle | 39 ----------- android/setupTBB.gradle | 31 -------- 9 files changed, 114 insertions(+), 283 deletions(-) delete mode 100644 android/setupBullet.gradle delete mode 100644 android/setupDraco.gradle delete mode 100644 android/setupOpenSSL.gradle delete mode 100644 android/setupPolyvox.gradle delete mode 100644 android/setupQt.gradle delete mode 100644 android/setupScribe.gradle delete mode 100644 android/setupTBB.gradle diff --git a/android/app/CMakeLists.txt b/android/app/CMakeLists.txt index 2451a8804c..8b36f8a1fb 100644 --- a/android/app/CMakeLists.txt +++ b/android/app/CMakeLists.txt @@ -3,9 +3,10 @@ setup_hifi_library() link_hifi_libraries(shared networking gl gpu gpu-gles image fbx render-utils physics) target_opengl() target_link_libraries(native-lib android log m) + set(GVR_ROOT "${HIFI_ANDROID_PRECOMPILED}/gvr/gvr-android-sdk-1.101.0/") target_include_directories(native-lib PRIVATE "${GVR_ROOT}/libraries/headers") -target_link_libraries(native-lib "${HIFI_ANDROID_PRECOMPILED}/jni/arm64-v8a/libgvr.so") +target_link_libraries(native-lib "${GVR_ROOT}/libraries/libgvr.so") # finished libraries # core -> qt diff --git a/android/build.gradle b/android/build.gradle index 43cdb0e8ac..a4c6da1432 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,6 +8,10 @@ buildscript { } } +plugins { + id 'de.undercouch.download' version '3.3.0' +} + allprojects { repositories { jcenter() @@ -15,42 +19,126 @@ allprojects { } } -task setupDependencies(type: Copy) { - from HIFI_ANDROID_PRECOMPILED + '/jni/arm64-v8a' - into 'app/src/main/jniLibs/arm64-v8a' + +def baseFolder = new File(HIFI_ANDROID_PRECOMPILED) +def jniFolder = new File('app/src/main/jniLibs/arm64-v8a') + +import org.apache.tools.ant.taskdefs.condition.Os + +def baseUrl = 'https://hifi-public.s3.amazonaws.com/austin/android/' +def qtFile='qt-5.9.3_linux_armv8-libcpp.tgz' +if (Os.isFamily(Os.FAMILY_MAC)) { + qtFile = 'qt-5.9.3_osx_armv8-libcpp.tgz' +} else if (Os.isFamily(Os.FAMILY_WINDOWS)) { + qtFile = 'qt-5.9.3_win_armv8-libcpp.tgz' } -apply from: 'setupQt.gradle' -setupDependencies.dependsOn setupQt +def packages = [ + qt: [ file: qtFile, sharedLibFolder: '', includeLibs: ['lib/*.so', 'plugins/*/*.so'] ], + bullet: [ file: 'bullet-2.83_armv8-libcpp.tgz' ], + draco: [ file: 'draco_armv8-libcpp.tgz' ], + gvr: [ file: 'gvrsdk_v1.101.0.tgz' ], + openssl: [ file: 'openssl-1.1.0g_armv8.tgz'], + polyvox: [ file: 'polyvox_armv8-libcpp.tgz', sharedLibFolder: 'lib', includeLibs: ['Release/libPolyVoxCore.so', 'libPolyVoxUtil.so'] ], + tbb: [ file: 'tbb-2018_U1_armv8_libcpp.tgz', sharedLibFolder: 'lib/release', includeLibs: ['libtbb.so', 'libtbbmalloc.so'] ] +] -apply from: 'setupScribe.gradle' -setupDependencies.dependsOn setupScribe +task downloadDependencies { + doLast { + packages.each { entry -> + def filename = entry.value['file']; + def url = baseUrl + filename; + download { + src url + dest new File(baseFolder, filename) + onlyIfNewer true + } + } + } +} -apply from: 'setupOpenSSL.gradle' -setupDependencies.dependsOn setupOpenSSL +task extractDependencies(dependsOn: downloadDependencies) { + doLast { + packages.each { entry -> + def folder = entry.key; + def filename = entry.value['file']; + def localFile = new File(HIFI_ANDROID_PRECOMPILED, filename) + def localFolder = new File(HIFI_ANDROID_PRECOMPILED, folder) + copy { + from tarTree(resources.gzip(localFile)) + into localFolder + } + } + } +} -apply from: 'setupTBB.gradle' -setupDependencies.dependsOn setupTBB +task copyDependencies(dependsOn: extractDependencies) { + doLast { + packages.each { entry -> + def packageName = entry.key + def currentPackage = entry.value; + if (currentPackage.containsKey('sharedLibFolder')) { + def localFolder = new File(baseFolder, packageName + '/' + currentPackage['sharedLibFolder']) + def tree = fileTree(localFolder); + if (currentPackage.containsKey('includeLibs')) { + currentPackage['includeLibs'].each { includeSpec -> tree.include includeSpec } + } + tree.visit { element -> + if (!element.file.isDirectory()) { + copy { from element.file; into jniFolder } + } + } + } + } + } +} -apply from: 'setupGVR.gradle' -setupDependencies.dependsOn setupGVR +task setupScribe(type: Exec) { + def scribeFile='scribe_linux_x86_64' + def scribeLocalFile='scribe' + if (Os.isFamily(Os.FAMILY_MAC)) { + scribeFile = 'scribe_osx_x86_64' + } else if (Os.isFamily(Os.FAMILY_WINDOWS)) { + scribeFile = 'scribe_win32_x86_64.exe' + scribeLocalFile = 'scribe.exe' + } -apply from: 'setupDraco.gradle' -setupDependencies.dependsOn setupDraco + doFirst { + download { + src baseUrl + scribeFile + dest new File(baseFolder, scribeLocalFile) + onlyIfNewer true + } + } + if (!Os.isFamily(Os.FAMILY_WINDOWS)) { + commandLine 'chmod', 'a+x', HIFI_ANDROID_PRECOMPILED + '/' + scribeLocalFile + } +} -apply from: 'setupBullet.gradle' -setupDependencies.dependsOn setupBullet - -apply from: 'setupPolyvox.gradle' -setupDependencies.dependsOn setupPolyvox - -task copyDependencies(type: Copy) { - from HIFI_ANDROID_PRECOMPILED + '/jni/arm64-v8a' - into 'app/src/main/jniLibs/arm64-v8a' +task setupDependencies(dependsOn: [setupScribe, copyDependencies]) { + doLast { + def gvrLibFolder = new File(HIFI_ANDROID_PRECOMPILED, 'gvr/gvr-android-sdk-1.101.0/libraries'); + zipTree(new File(HIFI_ANDROID_PRECOMPILED, 'gvr/gvr-android-sdk-1.101.0/libraries/sdk-audio-1.101.0.aar')).visit { element -> + if (element.file.toString().endsWith('arm64-v8a/libgvr_audio.so')) { + copy { from element.file; into gvrLibFolder } + } + } + zipTree(new File(HIFI_ANDROID_PRECOMPILED, 'gvr/gvr-android-sdk-1.101.0/libraries/sdk-base-1.101.0.aar')).visit { element -> + if (element.file.toString().endsWith('arm64-v8a/libgvr.so')) { + copy { from element.file; into gvrLibFolder } + } + } + fileTree(gvrLibFolder).visit { element -> + if (element.file.toString().endsWith('.so')) { + copy { from element.file; into jniFolder } + } + } + } } task cleanDependencies(type: Delete) { delete HIFI_ANDROID_PRECOMPILED + delete 'app/src/main/jniLibs/arm64-v8a' } task clean(type: Delete) { diff --git a/android/setupBullet.gradle b/android/setupBullet.gradle deleted file mode 100644 index 5fb1bd4369..0000000000 --- a/android/setupBullet.gradle +++ /dev/null @@ -1,26 +0,0 @@ -buildscript { - repositories { - jcenter() - google() - } - dependencies { - classpath 'com.android.tools.build:gradle:3.0.1' - classpath 'de.undercouch:gradle-download-task:3.3.0' - } -} - -def file='bullet-2.83_armv8-libcpp.tgz ' -def url='https://hifi-public.s3.amazonaws.com/austin/android/' + file -def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) - -task downloadBullet(type: de.undercouch.gradle.tasks.download.Download) { - src url - dest destFile -} - -task extractBullet(dependsOn: downloadBullet, type: Copy) { - from tarTree(resources.gzip(destFile)) - into new File(HIFI_ANDROID_PRECOMPILED, 'bullet') -} - -task setupBullet(dependsOn: extractBullet) { } diff --git a/android/setupDraco.gradle b/android/setupDraco.gradle deleted file mode 100644 index cae24b8a0f..0000000000 --- a/android/setupDraco.gradle +++ /dev/null @@ -1,26 +0,0 @@ -buildscript { - repositories { - jcenter() - google() - } - dependencies { - classpath 'com.android.tools.build:gradle:3.0.1' - classpath 'de.undercouch:gradle-download-task:3.3.0' - } -} - -def file='draco_armv8-libcpp.tgz' -def url='https://hifi-public.s3.amazonaws.com/austin/android/' + file -def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) - -task downloadDraco(type: de.undercouch.gradle.tasks.download.Download) { - src url - dest destFile -} - -task extractDraco(dependsOn: downloadDraco, type: Copy) { - from tarTree(resources.gzip(destFile)) - into new File(HIFI_ANDROID_PRECOMPILED, 'draco') -} - -task setupDraco(dependsOn: extractDraco) { } diff --git a/android/setupOpenSSL.gradle b/android/setupOpenSSL.gradle deleted file mode 100644 index 2a76405dda..0000000000 --- a/android/setupOpenSSL.gradle +++ /dev/null @@ -1,26 +0,0 @@ -buildscript { - repositories { - jcenter() - google() - } - dependencies { - classpath 'com.android.tools.build:gradle:3.0.1' - classpath 'de.undercouch:gradle-download-task:3.3.0' - } -} - -def file='openssl-1.1.0g_armv8.tgz' -def url='https://hifi-public.s3.amazonaws.com/austin/android/' + file -def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) - -task downloadOpenSSL(type: de.undercouch.gradle.tasks.download.Download) { - src url - dest destFile -} - -task extractOpenSSL(dependsOn: downloadOpenSSL, type: Copy) { - from tarTree(resources.gzip(destFile)) - into new File(HIFI_ANDROID_PRECOMPILED, 'openssl') -} - -task setupOpenSSL(dependsOn: extractOpenSSL) { } diff --git a/android/setupPolyvox.gradle b/android/setupPolyvox.gradle deleted file mode 100644 index 168fbd9b15..0000000000 --- a/android/setupPolyvox.gradle +++ /dev/null @@ -1,38 +0,0 @@ -buildscript { - repositories { - jcenter() - google() - } - dependencies { - classpath 'com.android.tools.build:gradle:3.0.1' - classpath 'de.undercouch:gradle-download-task:3.3.0' - } -} - -def file='polyvox_armv8-libcpp.tgz' -def url='https://hifi-public.s3.amazonaws.com/austin/android/' + file -def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) - -task downloadPolyvox(type: de.undercouch.gradle.tasks.download.Download) { - src url - dest destFile -} - -task extractPolyvox(dependsOn: downloadPolyvox, type: Copy) { - from tarTree(resources.gzip(destFile)) - into new File(HIFI_ANDROID_PRECOMPILED, 'polyvox') -} - -task copyPolyvoxCore(dependsOn: extractPolyvox, type: Copy) { - from HIFI_ANDROID_PRECOMPILED + '/polyvox/lib/Release' - include 'libPolyVoxCore.so' - into HIFI_ANDROID_PRECOMPILED + '/jni/arm64-v8a' -} - -task copyPolyvoxUtil(dependsOn: extractPolyvox, type: Copy) { - from HIFI_ANDROID_PRECOMPILED + '/polyvox/lib' - include 'libPolyVoxUtil.so' - into HIFI_ANDROID_PRECOMPILED + '/jni/arm64-v8a' -} - -task setupPolyvox(dependsOn: [copyPolyvoxCore, copyPolyvoxUtil]) { } diff --git a/android/setupQt.gradle b/android/setupQt.gradle deleted file mode 100644 index 32a87d9580..0000000000 --- a/android/setupQt.gradle +++ /dev/null @@ -1,72 +0,0 @@ -buildscript { - repositories { - jcenter() - google() - } - dependencies { - classpath 'com.android.tools.build:gradle:3.0.1' - classpath 'de.undercouch:gradle-download-task:3.3.0' - } -} - - -import org.apache.tools.ant.taskdefs.condition.Os - -def file='qt-5.9.3_linux_armv8-libcpp.tgz' -if (Os.isFamily(Os.FAMILY_MAC)) { - file = 'qt-5.9.3_osx_armv8-libcpp.tgz' -} else if (Os.isFamily(Os.FAMILY_WINDOWS)) { - file = 'qt-5.9.3_win_armv8-libcpp.tgz' -} - -def url='https://hifi-public.s3.amazonaws.com/austin/android/' + file -def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) - -task downloadQt(type: de.undercouch.gradle.tasks.download.Download) { - src url - dest destFile -} - -task extractQt(dependsOn: downloadQt, type: Copy) { - from tarTree(resources.gzip(destFile)) - into new File(HIFI_ANDROID_PRECOMPILED, 'qt') -} - -task copyQtJars(dependsOn: extractQt, type: Copy) { - from HIFI_ANDROID_PRECOMPILED + '/qt/jar' - include '*.jar' - into HIFI_ANDROID_PRECOMPILED + '/jar' -} - -task copyQtLibs(dependsOn: extractQt, type: Copy) { - from HIFI_ANDROID_PRECOMPILED + '/qt/lib' - include 'libQt5AndroidExtras.so' - include 'libQt5Concurrent.so' - include 'libQt5Core.so' - include 'libQt5Gamepad.so' - include 'libQt5Gui.so' - include 'libQt5MultimediaQuick_p.so' - include 'libQt5Multimedia.so' - include 'libQt5Network.so' - include 'libQt5OpenGL.so' - include 'libQt5Qml.so' - include 'libQt5QuickControls2.so' - include 'libQt5QuickParticles.so' - include 'libQt5Quick.so' - include 'libQt5QuickTemplates2.so' - include 'libQt5QuickWidgets.so' - include 'libQt5Script.so' - include 'libQt5ScriptTools.so' - include 'libQt5Scxml.so' - include 'libQt5Svg.so' - include 'libQt5WebChannel.so' - include 'libQt5WebSockets.so' - include 'libQt5WebView.so' - include 'libQt5Widgets.so' - include 'libQt5XmlPatterns.so' - include 'libQt5Xml.so' - into HIFI_ANDROID_PRECOMPILED + '/jni/arm64-v8a' -} - -task setupQt(dependsOn: [copyQtLibs, copyQtJars]) { -} diff --git a/android/setupScribe.gradle b/android/setupScribe.gradle deleted file mode 100644 index b415715309..0000000000 --- a/android/setupScribe.gradle +++ /dev/null @@ -1,39 +0,0 @@ -buildscript { - repositories { - jcenter() - google() - } - dependencies { - classpath 'com.android.tools.build:gradle:3.0.1' - classpath 'de.undercouch:gradle-download-task:3.3.0' - } -} - -import org.apache.tools.ant.taskdefs.condition.Os - -def file='scribe_linux_x86_64' -def localFile='scribe' -if (Os.isFamily(Os.FAMILY_MAC)) { - file = 'scribe_osx_x86_64' -} else if (Os.isFamily(Os.FAMILY_WINDOWS)) { - file = 'scribe_win32_x86_64.exe' - localFile = 'scribe.exe' -} - -def url='https://hifi-public.s3.amazonaws.com/austin/android/' + file -def destFile = new File(HIFI_ANDROID_PRECOMPILED, localFile) - -task filepermission(type: Exec) { - if (!Os.isFamily(Os.FAMILY_WINDOWS)) { - commandLine 'chmod', '700', '' - } -} - -task downloadScribe(type: de.undercouch.gradle.tasks.download.Download) { - src url - dest destFile -} - -task setupScribe(dependsOn: downloadScribe, type: Exec) { - commandLine 'chmod', 'a+x', destFile -} diff --git a/android/setupTBB.gradle b/android/setupTBB.gradle deleted file mode 100644 index 55d7a9164e..0000000000 --- a/android/setupTBB.gradle +++ /dev/null @@ -1,31 +0,0 @@ -buildscript { - repositories { - jcenter() - google() - } - dependencies { - classpath 'com.android.tools.build:gradle:3.0.1' - classpath 'de.undercouch:gradle-download-task:3.3.0' - } -} - -def file='tbb-2018_U1_armv8_libcpp.tgz' -def url='https://hifi-public.s3.amazonaws.com/austin/android/' + file -def destFile = new File(HIFI_ANDROID_PRECOMPILED, file) - -task downloadTBB(type: de.undercouch.gradle.tasks.download.Download) { - src url - dest destFile -} - -task extractTBB(dependsOn: downloadTBB, type: Copy) { - from tarTree(resources.gzip(destFile)) - into new File(HIFI_ANDROID_PRECOMPILED, 'tbb') -} - -task setupTBB(dependsOn: extractTBB, type: Copy) { - from HIFI_ANDROID_PRECOMPILED + '/tbb/lib/release' - include 'libtbb.so' - include 'libtbbmalloc.so' - into HIFI_ANDROID_PRECOMPILED + '/jni/arm64-v8a/' -} From 8d6d1f67f1d52a28fdd89e4290d0ee5b359ddaff Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 28 Nov 2017 09:00:58 -0800 Subject: [PATCH 18/30] Support RELEASE_TYPE and RELEASE_NUM for Android --- android/app/build.gradle | 17 ++++++++-- android/build.gradle | 40 ++++++++++++++--------- cmake/macros/SetFromEnv.cmake | 17 ++++++++++ cmake/macros/SetPackagingParameters.cmake | 9 ++--- cmake/macros/SetupQt.cmake | 14 ++------ 5 files changed, 63 insertions(+), 34 deletions(-) create mode 100644 cmake/macros/SetFromEnv.cmake diff --git a/android/app/build.gradle b/android/app/build.gradle index 005ec1a3ad..199bc6f0c8 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,5 +1,10 @@ apply plugin: 'com.android.application' +ext.RELEASE_NUMBER = project.hasProperty('RELEASE_NUMBER') ? project.getProperty('RELEASE_NUMBER') : '0' +ext.RELEASE_TYPE = project.hasProperty('RELEASE_TYPE') ? project.getProperty('RELEASE_TYPE') : 'DEV' + + + android { compileSdkVersion 26 defaultConfig { @@ -17,7 +22,9 @@ android { '-DANDROID_STL=c++_shared', '-DQT_CMAKE_PREFIX_PATH=' + HIFI_ANDROID_PRECOMPILED + '/qt/lib/cmake', '-DNATIVE_SCRIBE=' + HIFI_ANDROID_PRECOMPILED + '/scribe', - '-DHIFI_ANDROID_PRECOMPILED=' + HIFI_ANDROID_PRECOMPILED + '-DHIFI_ANDROID_PRECOMPILED=' + HIFI_ANDROID_PRECOMPILED, + '-DRELEASE_NUMBER=' + RELEASE_NUMBER, + '-DRELEASE_TYPE=' + RELEASE_TYPE } } compileOptions { @@ -27,6 +34,12 @@ android { } buildTypes { + applicationVariants.all { variant -> + variant.outputs.all { + outputFileName = "app_" + RELEASE_NUMBER + "_" + RELEASE_TYPE + ".apk" + } + } + release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' @@ -45,4 +58,4 @@ dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.google.vr:sdk-audio:1.80.0' compile 'com.google.vr:sdk-base:1.80.0' -} \ No newline at end of file +} diff --git a/android/build.gradle b/android/build.gradle index a4c6da1432..cfa979909f 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -93,7 +93,7 @@ task copyDependencies(dependsOn: extractDependencies) { } } -task setupScribe(type: Exec) { +task setupScribe { def scribeFile='scribe_linux_x86_64' def scribeLocalFile='scribe' if (Os.isFamily(Os.FAMILY_MAC)) { @@ -110,30 +110,38 @@ task setupScribe(type: Exec) { onlyIfNewer true } } - if (!Os.isFamily(Os.FAMILY_WINDOWS)) { - commandLine 'chmod', 'a+x', HIFI_ANDROID_PRECOMPILED + '/' + scribeLocalFile + doLast { + if (!Os.isFamily(Os.FAMILY_WINDOWS)) { + commandLine 'chmod', 'a+x', HIFI_ANDROID_PRECOMPILED + '/' + scribeLocalFile + } } } -task setupDependencies(dependsOn: [setupScribe, copyDependencies]) { +task extractGvrBinaries(dependsOn: extractDependencies) { doLast { def gvrLibFolder = new File(HIFI_ANDROID_PRECOMPILED, 'gvr/gvr-android-sdk-1.101.0/libraries'); - zipTree(new File(HIFI_ANDROID_PRECOMPILED, 'gvr/gvr-android-sdk-1.101.0/libraries/sdk-audio-1.101.0.aar')).visit { element -> - if (element.file.toString().endsWith('arm64-v8a/libgvr_audio.so')) { - copy { from element.file; into gvrLibFolder } - } - } - zipTree(new File(HIFI_ANDROID_PRECOMPILED, 'gvr/gvr-android-sdk-1.101.0/libraries/sdk-base-1.101.0.aar')).visit { element -> - if (element.file.toString().endsWith('arm64-v8a/libgvr.so')) { - copy { from element.file; into gvrLibFolder } - } - } - fileTree(gvrLibFolder).visit { element -> + zipTree(new File(HIFI_ANDROID_PRECOMPILED, 'gvr/gvr-android-sdk-1.101.0/libraries/sdk-audio-1.101.0.aar')).visit { element -> + def fileName = element.file.toString(); + if (fileName.endsWith('libgvr_audio.so') && fileName.contains('arm64-v8a')) { + copy { from element.file; into gvrLibFolder } + } + } + zipTree(new File(HIFI_ANDROID_PRECOMPILED, 'gvr/gvr-android-sdk-1.101.0/libraries/sdk-base-1.101.0.aar')).visit { element -> + def fileName = element.file.toString(); + if (fileName.endsWith('libgvr.so') && fileName.contains('arm64-v8a')) { + copy { from element.file; into gvrLibFolder } + } + } + fileTree(gvrLibFolder).visit { element -> if (element.file.toString().endsWith('.so')) { copy { from element.file; into jniFolder } } - } + } } + +} + +task setupDependencies(dependsOn: [setupScribe, copyDependencies, extractGvrBinaries]) { } task cleanDependencies(type: Delete) { diff --git a/cmake/macros/SetFromEnv.cmake b/cmake/macros/SetFromEnv.cmake new file mode 100644 index 0000000000..0832c5a536 --- /dev/null +++ b/cmake/macros/SetFromEnv.cmake @@ -0,0 +1,17 @@ +# +# Created by Bradley Austin Davis on 2017/11/27 +# Copyright 2013-2017 High Fidelity, Inc. +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# + +function(set_from_env _RESULT_NAME _ENV_VAR_NAME _DEFAULT_VALUE) + if (NOT DEFINED ${_RESULT_NAME}) + if ("$ENV{${_ENV_VAR_NAME}}" STREQUAL "") + set (${_RESULT_NAME} ${_DEFAULT_VALUE} PARENT_SCOPE) + else() + set (${_RESULT_NAME} $ENV{${_ENV_VAR_NAME}} PARENT_SCOPE) + endif() + endif() +endfunction() diff --git a/cmake/macros/SetPackagingParameters.cmake b/cmake/macros/SetPackagingParameters.cmake index 8faa4e6d96..e26f81edd9 100644 --- a/cmake/macros/SetPackagingParameters.cmake +++ b/cmake/macros/SetPackagingParameters.cmake @@ -15,13 +15,14 @@ macro(SET_PACKAGING_PARAMETERS) set(PR_BUILD 0) set(PRODUCTION_BUILD 0) set(DEV_BUILD 0) - - set(RELEASE_TYPE $ENV{RELEASE_TYPE}) - set(RELEASE_NUMBER $ENV{RELEASE_NUMBER}) - string(TOLOWER "$ENV{BRANCH}" BUILD_BRANCH) set(BUILD_GLOBAL_SERVICES "DEVELOPMENT") set(USE_STABLE_GLOBAL_SERVICES 0) + set_from_env(RELEASE_TYPE RELEASE_TYPE "DEV") + set_from_env(RELEASE_NUMBER RELEASE_NUMBER "") + set_from_env(BUILD_BRANCH BRANCH "") + string(TOLOWER "${BUILD_BRANCH}" BUILD_BRANCH) + message(STATUS "The BUILD_BRANCH variable is: ${BUILD_BRANCH}") message(STATUS "The BRANCH environment variable is: $ENV{BRANCH}") message(STATUS "The RELEASE_TYPE variable is: ${RELEASE_TYPE}") diff --git a/cmake/macros/SetupQt.cmake b/cmake/macros/SetupQt.cmake index ac67e12044..00a398761b 100644 --- a/cmake/macros/SetupQt.cmake +++ b/cmake/macros/SetupQt.cmake @@ -1,21 +1,11 @@ # -# Copyright 2015 High Fidelity, Inc. -# Created by Bradley Austin Davis on 2015/10/10 +# Created by Bradley Austin Davis on 2017/09/02 +# Copyright 2013-2017 High Fidelity, Inc. # # Distributed under the Apache License, Version 2.0. # See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html # -function(set_from_env _RESULT_NAME _ENV_VAR_NAME _DEFAULT_VALUE) - if (NOT DEFINED ${_RESULT_NAME}) - if ("$ENV{${_ENV_VAR_NAME}}" STREQUAL "") - set (${_RESULT_NAME} ${_DEFAULT_VALUE} PARENT_SCOPE) - else() - set (${_RESULT_NAME} $ENV{${_ENV_VAR_NAME}} PARENT_SCOPE) - endif() - endif() -endfunction() - # Construct a default QT location from a root path, a version and an architecture function(calculate_default_qt_dir _RESULT_NAME) if (ANDROID) From 251ae81536a4b0224b31efdb93e0932eadefd6a4 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 28 Nov 2017 09:38:55 -0800 Subject: [PATCH 19/30] Adding verification to downloaded files for android --- android/build.gradle | 67 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index cfa979909f..ab66a69351 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -24,23 +24,55 @@ def baseFolder = new File(HIFI_ANDROID_PRECOMPILED) def jniFolder = new File('app/src/main/jniLibs/arm64-v8a') import org.apache.tools.ant.taskdefs.condition.Os +import de.undercouch.gradle.tasks.download.Verify + def baseUrl = 'https://hifi-public.s3.amazonaws.com/austin/android/' def qtFile='qt-5.9.3_linux_armv8-libcpp.tgz' +def qtChecksum='547da3547d5690144e23d6504c6d6e91' if (Os.isFamily(Os.FAMILY_MAC)) { qtFile = 'qt-5.9.3_osx_armv8-libcpp.tgz' + qtChecksum='6fa3e068cfdee863fc909b294a3a0cc6' } else if (Os.isFamily(Os.FAMILY_WINDOWS)) { qtFile = 'qt-5.9.3_win_armv8-libcpp.tgz' + qtChecksum='3a757378a7e9dbbfc662177e0eb46408' } def packages = [ - qt: [ file: qtFile, sharedLibFolder: '', includeLibs: ['lib/*.so', 'plugins/*/*.so'] ], - bullet: [ file: 'bullet-2.83_armv8-libcpp.tgz' ], - draco: [ file: 'draco_armv8-libcpp.tgz' ], - gvr: [ file: 'gvrsdk_v1.101.0.tgz' ], - openssl: [ file: 'openssl-1.1.0g_armv8.tgz'], - polyvox: [ file: 'polyvox_armv8-libcpp.tgz', sharedLibFolder: 'lib', includeLibs: ['Release/libPolyVoxCore.so', 'libPolyVoxUtil.so'] ], - tbb: [ file: 'tbb-2018_U1_armv8_libcpp.tgz', sharedLibFolder: 'lib/release', includeLibs: ['libtbb.so', 'libtbbmalloc.so'] ] + qt: [ + file: qtFile, + checksum: qtChecksum, + sharedLibFolder: '', + includeLibs: ['lib/*.so', 'plugins/*/*.so'] + ], + bullet: [ + file: 'bullet-2.83_armv8-libcpp.tgz', + checksum: '2c558d604fce337f5eba3eb7ec1252fd' + ], + draco: [ + file: 'draco_armv8-libcpp.tgz', + checksum: '617a80d213a5ec69fbfa21a1f2f738cd' + ], + gvr: [ + file: 'gvrsdk_v1.101.0.tgz', + checksum: '57fd02baa069176ba18597a29b6b4fc7' + ], + openssl: [ + file: 'openssl-1.1.0g_armv8.tgz', + checksum: 'cabb681fbccd79594f65fcc266e02f32' + ], + polyvox: [ + file: 'polyvox_armv8-libcpp.tgz', + checksum: '5c918288741ee754c16aeb12bb46b9e1', + sharedLibFolder: 'lib', + includeLibs: ['Release/libPolyVoxCore.so', 'libPolyVoxUtil.so'] + ], + tbb: [ + file: 'tbb-2018_U1_armv8_libcpp.tgz', + checksum: '20768f298f53b195e71b414b0ae240c4', + sharedLibFolder: 'lib/release', + includeLibs: ['libtbb.so', 'libtbbmalloc.so'] + ] ] task downloadDependencies { @@ -52,12 +84,29 @@ task downloadDependencies { src url dest new File(baseFolder, filename) onlyIfNewer true - } + } } } } -task extractDependencies(dependsOn: downloadDependencies) { +task verifyQt(type: Verify) { def p = packages['qt']; src new File(baseFolder, p['file']); checksum p['checksum']; } +task verifyBullet(type: Verify) { def p = packages['bullet']; src new File(baseFolder, p['file']); checksum p['checksum'] } +task verifyDraco(type: Verify) { def p = packages['draco']; src new File(baseFolder, p['file']); checksum p['checksum'] } +task verifyGvr(type: Verify) { def p = packages['gvr']; src new File(baseFolder, p['file']); checksum p['checksum'] } +task verifyOpenSSL(type: Verify) { def p = packages['openssl']; src new File(baseFolder, p['file']); checksum p['checksum'] } +task verifyPolyvox(type: Verify) { def p = packages['polyvox']; src new File(baseFolder, p['file']); checksum p['checksum'] } +task verifyTBB(type: Verify) { def p = packages['tbb']; src new File(baseFolder, p['file']); checksum p['checksum'] } + +task verifyDependencyDownloads(dependsOn: downloadDependencies) { } +verifyDependencyDownloads.dependsOn verifyQt +verifyDependencyDownloads.dependsOn verifyBullet +verifyDependencyDownloads.dependsOn verifyDraco +verifyDependencyDownloads.dependsOn verifyGvr +verifyDependencyDownloads.dependsOn verifyOpenSSL +verifyDependencyDownloads.dependsOn verifyPolyvox +verifyDependencyDownloads.dependsOn verifyTBB + +task extractDependencies(dependsOn: verifyDependencyDownloads) { doLast { packages.each { entry -> def folder = entry.key; From 300e1835eb21e71ca7f0e372b4e4bfd9ebda5567 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 28 Nov 2017 12:20:52 -0800 Subject: [PATCH 20/30] Fix scribe permissions setting --- android/build.gradle | 59 +++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index ab66a69351..75b1b7ad4e 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -24,8 +24,6 @@ def baseFolder = new File(HIFI_ANDROID_PRECOMPILED) def jniFolder = new File('app/src/main/jniLibs/arm64-v8a') import org.apache.tools.ant.taskdefs.condition.Os -import de.undercouch.gradle.tasks.download.Verify - def baseUrl = 'https://hifi-public.s3.amazonaws.com/austin/android/' def qtFile='qt-5.9.3_linux_armv8-libcpp.tgz' @@ -89,6 +87,8 @@ task downloadDependencies { } } +import de.undercouch.gradle.tasks.download.Verify + task verifyQt(type: Verify) { def p = packages['qt']; src new File(baseFolder, p['file']); checksum p['checksum']; } task verifyBullet(type: Verify) { def p = packages['bullet']; src new File(baseFolder, p['file']); checksum p['checksum'] } task verifyDraco(type: Verify) { def p = packages['draco']; src new File(baseFolder, p['file']); checksum p['checksum'] } @@ -142,28 +142,41 @@ task copyDependencies(dependsOn: extractDependencies) { } } -task setupScribe { - def scribeFile='scribe_linux_x86_64' - def scribeLocalFile='scribe' - if (Os.isFamily(Os.FAMILY_MAC)) { - scribeFile = 'scribe_osx_x86_64' - } else if (Os.isFamily(Os.FAMILY_WINDOWS)) { - scribeFile = 'scribe_win32_x86_64.exe' - scribeLocalFile = 'scribe.exe' - } +def scribeFile='scribe_linux_x86_64' +def scribeLocalFile='scribe' +def scribeChecksum='c98678d9726bd8bbf1bab792acf3ff6c' +if (Os.isFamily(Os.FAMILY_MAC)) { + scribeFile = 'scribe_osx_x86_64' + scribeChecksum='a137ad62c1bf7cca739da219544a9a16' +} else if (Os.isFamily(Os.FAMILY_WINDOWS)) { + scribeFile = 'scribe_win32_x86_64.exe' + scribeLocalFile = 'scribe.exe' + scribeChecksum='75c2ce9ed45d17de375e3988bfaba816' - doFirst { - download { - src baseUrl + scribeFile - dest new File(baseFolder, scribeLocalFile) - onlyIfNewer true - } - } - doLast { - if (!Os.isFamily(Os.FAMILY_WINDOWS)) { - commandLine 'chmod', 'a+x', HIFI_ANDROID_PRECOMPILED + '/' + scribeLocalFile - } - } +} + +import de.undercouch.gradle.tasks.download.Download + +task downloadScribe(type: Download) { + src baseUrl + scribeFile + dest new File(baseFolder, scribeLocalFile) + onlyIfNewer true +} + +task verifyScribe (type: Verify, dependsOn: downloadScribe) { + src new File(baseFolder, scribeLocalFile); + checksum scribeChecksum +} + +task fixScribePermissions(type: Exec, dependsOn: verifyScribe) { + commandLine 'chmod', 'a+x', HIFI_ANDROID_PRECOMPILED + '/' + scribeLocalFile +} + +task setupScribe(dependsOn: verifyScribe) { } + +// On Windows, we don't need to set the executable bit, but on OSX and Unix we do +if (!Os.isFamily(Os.FAMILY_WINDOWS)) { + setupScribe.dependsOn fixScribePermissions } task extractGvrBinaries(dependsOn: extractDependencies) { From 72792552c849174409f99fa070fb0cae028bd246 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 28 Nov 2017 12:30:39 -0800 Subject: [PATCH 21/30] Add BUILD_BRANCH to the parameters passed to cmake --- android/app/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 199bc6f0c8..b599ce1a14 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -2,8 +2,7 @@ apply plugin: 'com.android.application' ext.RELEASE_NUMBER = project.hasProperty('RELEASE_NUMBER') ? project.getProperty('RELEASE_NUMBER') : '0' ext.RELEASE_TYPE = project.hasProperty('RELEASE_TYPE') ? project.getProperty('RELEASE_TYPE') : 'DEV' - - +ext.BUILD_BRANCH = project.hasProperty('BUILD_BRANCH') ? project.getProperty('BUILD_BRANCH') : '' android { compileSdkVersion 26 @@ -24,7 +23,8 @@ android { '-DNATIVE_SCRIBE=' + HIFI_ANDROID_PRECOMPILED + '/scribe', '-DHIFI_ANDROID_PRECOMPILED=' + HIFI_ANDROID_PRECOMPILED, '-DRELEASE_NUMBER=' + RELEASE_NUMBER, - '-DRELEASE_TYPE=' + RELEASE_TYPE + '-DRELEASE_TYPE=' + RELEASE_TYPE, + '-DBUILD_BRANCH=' + BUILD_BRANCH } } compileOptions { From 137118c7fd69664b494e44e4198428f1b91ba405 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 28 Nov 2017 12:35:10 -0800 Subject: [PATCH 22/30] Conditionally rename the APK for Jenkins --- android/app/build.gradle | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index b599ce1a14..29b7e4a6cc 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -36,7 +36,9 @@ android { buildTypes { applicationVariants.all { variant -> variant.outputs.all { - outputFileName = "app_" + RELEASE_NUMBER + "_" + RELEASE_TYPE + ".apk" + if (RELEASE_NUMBER != '0') { + outputFileName = "app_" + RELEASE_NUMBER + "_" + RELEASE_TYPE + ".apk" + } } } From a30395e945e4f7f2f445687b47ae592f39d77122 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 28 Nov 2017 13:45:49 -0800 Subject: [PATCH 23/30] Tweaking android cmake --- android/app/CMakeLists.txt | 18 +++--------------- cmake/macros/TargetGoogleVR.cmake | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 15 deletions(-) create mode 100644 cmake/macros/TargetGoogleVR.cmake diff --git a/android/app/CMakeLists.txt b/android/app/CMakeLists.txt index 8b36f8a1fb..3d4516d0bf 100644 --- a/android/app/CMakeLists.txt +++ b/android/app/CMakeLists.txt @@ -1,22 +1,10 @@ set(TARGET_NAME native-lib) setup_hifi_library() link_hifi_libraries(shared networking gl gpu gpu-gles image fbx render-utils physics) -target_opengl() + target_link_libraries(native-lib android log m) -set(GVR_ROOT "${HIFI_ANDROID_PRECOMPILED}/gvr/gvr-android-sdk-1.101.0/") -target_include_directories(native-lib PRIVATE "${GVR_ROOT}/libraries/headers") -target_link_libraries(native-lib "${GVR_ROOT}/libraries/libgvr.so") - -# finished libraries -# core -> qt -# networking -> openssl, tbb -# fbx -> draco -# physics -> bullet -# entities-renderer -> polyvox - -# unfinished libraries -# image -> nvtt (doesn't look good, but can be made optional) -# script-engine -> quazip (probably not required for the android client) +target_opengl() +target_googlevr() diff --git a/cmake/macros/TargetGoogleVR.cmake b/cmake/macros/TargetGoogleVR.cmake new file mode 100644 index 0000000000..eca5d655f9 --- /dev/null +++ b/cmake/macros/TargetGoogleVR.cmake @@ -0,0 +1,14 @@ +# +# Copyright 2015 High Fidelity, Inc. +# Created by Bradley Austin Davis on 2015/10/10 +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# +macro(TARGET_GOOGLEVR) + if (ANDROID) + set(GVR_ROOT "${HIFI_ANDROID_PRECOMPILED}/gvr/gvr-android-sdk-1.101.0/") + target_include_directories(native-lib PRIVATE "${GVR_ROOT}/libraries/headers") + target_link_libraries(native-lib "${GVR_ROOT}/libraries/libgvr.so") + endif() +endmacro() From 5febbc32f5d44ec1bd01c3294767ed68b8e9eabf Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 28 Nov 2017 13:54:46 -0800 Subject: [PATCH 24/30] CMake header cleanup --- cmake/macros/TargetGoogleVR.cmake | 4 ++-- cmake/macros/TargetPolyvox.cmake | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/macros/TargetGoogleVR.cmake b/cmake/macros/TargetGoogleVR.cmake index eca5d655f9..852037770d 100644 --- a/cmake/macros/TargetGoogleVR.cmake +++ b/cmake/macros/TargetGoogleVR.cmake @@ -1,6 +1,6 @@ # -# Copyright 2015 High Fidelity, Inc. -# Created by Bradley Austin Davis on 2015/10/10 +# Created by Bradley Austin Davis on 2017/11/28 +# Copyright 2013-2017 High Fidelity, Inc. # # Distributed under the Apache License, Version 2.0. # See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html diff --git a/cmake/macros/TargetPolyvox.cmake b/cmake/macros/TargetPolyvox.cmake index f03a1ec42f..9db6b522c7 100644 --- a/cmake/macros/TargetPolyvox.cmake +++ b/cmake/macros/TargetPolyvox.cmake @@ -1,6 +1,6 @@ # -# Copyright 2015 High Fidelity, Inc. -# Created by Bradley Austin Davis on 2015/10/10 +# Created by Bradley Austin Davis on 2017/11/28 +# Copyright 2013-2017 High Fidelity, Inc. # # Distributed under the Apache License, Version 2.0. # See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html From e4220aa44eb5f535546bc2e289f22cb34e1cd8c2 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Tue, 28 Nov 2017 14:32:30 -0800 Subject: [PATCH 25/30] Fixing warnings in android build --- android/app/src/main/cpp/renderer.cpp | 2 ++ libraries/entities/src/EntityEditFilters.cpp | 2 +- libraries/gpu-gles/src/gpu/gl/GLBackend.cpp | 2 +- libraries/gpu-gles/src/gpu/gl/GLBackendQuery.cpp | 4 ++-- libraries/gpu-gles/src/gpu/gl/GLBackendState.cpp | 4 ++-- libraries/gpu-gles/src/gpu/gl/GLTexelFormat.cpp | 10 ++++++++++ libraries/gpu-gles/src/gpu/gles/GLESBackend.cpp | 8 +++----- libraries/gpu-gles/src/gpu/gles/GLESBackendOutput.cpp | 3 ++- libraries/render-utils/src/CauterizedModel.cpp | 2 +- libraries/render-utils/src/LightStage.cpp | 2 +- 10 files changed, 25 insertions(+), 14 deletions(-) diff --git a/android/app/src/main/cpp/renderer.cpp b/android/app/src/main/cpp/renderer.cpp index 9c9c9f8b52..27e4a7d882 100644 --- a/android/app/src/main/cpp/renderer.cpp +++ b/android/app/src/main/cpp/renderer.cpp @@ -147,6 +147,7 @@ static void CheckGLError(const char* label) { } // Contains vertex, normal and other data. +#if 0 namespace cube { const std::array CUBE_COORDS{{ // Front face @@ -298,6 +299,7 @@ namespace cube { 0.0f, -1.0f, 0.0f }}; } +#endif namespace triangle { static std::array TRIANGLE_VERTS {{ diff --git a/libraries/entities/src/EntityEditFilters.cpp b/libraries/entities/src/EntityEditFilters.cpp index 5359ebd31b..550c8f17c4 100644 --- a/libraries/entities/src/EntityEditFilters.cpp +++ b/libraries/entities/src/EntityEditFilters.cpp @@ -199,7 +199,7 @@ void EntityEditFilters::scriptRequestFinished(EntityItemID entityID) { // define the uncaughtException function QScriptEngine& engineRef = *engine; - filterData.uncaughtExceptions = [this, &engineRef, urlString]() { return hadUncaughtExceptions(engineRef, urlString); }; + filterData.uncaughtExceptions = [&engineRef, urlString]() { return hadUncaughtExceptions(engineRef, urlString); }; // now get the filter function auto global = engine->globalObject(); diff --git a/libraries/gpu-gles/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gles/src/gpu/gl/GLBackend.cpp index 1d66618703..cb00d00b3e 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gles/src/gpu/gl/GLBackend.cpp @@ -37,7 +37,7 @@ static const char* GL_BACKEND_PROPERTY_NAME = "com.highfidelity.gl.backend"; BackendPointer GLBackend::createBackend() { // FIXME provide a mechanism to override the backend for testing // Where the gpuContext is initialized and where the TRUE Backend is created and assigned - auto version = QOpenGLContextWrapper::currentContextVersion(); + //auto version = QOpenGLContextWrapper::currentContextVersion(); std::shared_ptr result; qDebug() << "Using OpenGL ES backend"; diff --git a/libraries/gpu-gles/src/gpu/gl/GLBackendQuery.cpp b/libraries/gpu-gles/src/gpu/gl/GLBackendQuery.cpp index 530e01d8ff..e5126bb3df 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLBackendQuery.cpp +++ b/libraries/gpu-gles/src/gpu/gl/GLBackendQuery.cpp @@ -17,10 +17,10 @@ using namespace gpu::gl; // Eventually, we want to test with TIME_ELAPSED instead of TIMESTAMP #ifdef Q_OS_MAC -const uint32_t MAX_RANGE_QUERY_DEPTH = 1; +//const uint32_t MAX_RANGE_QUERY_DEPTH = 1; static bool timeElapsed = true; #else -const uint32_t MAX_RANGE_QUERY_DEPTH = 10000; +//const uint32_t MAX_RANGE_QUERY_DEPTH = 10000; static bool timeElapsed = false; #endif diff --git a/libraries/gpu-gles/src/gpu/gl/GLBackendState.cpp b/libraries/gpu-gles/src/gpu/gl/GLBackendState.cpp index 27b8d23bf3..0a7db78b11 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLBackendState.cpp +++ b/libraries/gpu-gles/src/gpu/gl/GLBackendState.cpp @@ -56,11 +56,11 @@ void GLBackend::syncPipelineStateCache() { void GLBackend::do_setStateFillMode(int32 mode) { if (_pipeline._stateCache.fillMode != mode) { - static GLenum GL_FILL_MODES[] = { /*GL_POINT, GL_LINE, GL_FILL*/ }; + //static GLenum GL_FILL_MODES[] = { /*GL_POINT, GL_LINE, GL_FILL*/ }; + //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL_MODES[mode]); qDebug() << "TODO: GLBackendState.cpp:do_setStateFillMode GL_POINT"; qDebug() << "TODO: GLBackendState.cpp:do_setStateFillMode GL_LINE"; qDebug() << "TODO: GLBackendState.cpp:do_setStateFillMode GL_FILL"; - //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL_MODES[mode]); qDebug() << "TODO: GLBackendState.cpp:do_setStateFillMode glPolygonMode"; (void)CHECK_GL_ERROR(); diff --git a/libraries/gpu-gles/src/gpu/gl/GLTexelFormat.cpp b/libraries/gpu-gles/src/gpu/gl/GLTexelFormat.cpp index 6eec4b5292..9808d389f1 100644 --- a/libraries/gpu-gles/src/gpu/gl/GLTexelFormat.cpp +++ b/libraries/gpu-gles/src/gpu/gl/GLTexelFormat.cpp @@ -178,6 +178,10 @@ GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) { case gpu::NINT8: result = GL_RGBA8_SNORM; break; + case gpu::COMPRESSED: + case gpu::NUINT2: + case gpu::NINT16: + case gpu::NUINT16: case gpu::NUINT32: case gpu::NINT32: case gpu::NUM_TYPES: // quiet compiler @@ -446,6 +450,8 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E texel.internalFormat = GL_R8_SNORM; break; } + case gpu::COMPRESSED: + case gpu::NUINT2: case gpu::NUM_TYPES: { // quiet compiler Q_UNREACHABLE(); } @@ -489,6 +495,8 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E texel.internalFormat = GL_DEPTH_COMPONENT24; break; } + case gpu::COMPRESSED: + case gpu::NUINT2: case gpu::NUM_TYPES: { // quiet compiler Q_UNREACHABLE(); } @@ -614,6 +622,8 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E break; case gpu::NUINT32: case gpu::NINT32: + case gpu::COMPRESSED: + case gpu::NUINT2: case gpu::NUM_TYPES: // quiet compiler Q_UNREACHABLE(); } diff --git a/libraries/gpu-gles/src/gpu/gles/GLESBackend.cpp b/libraries/gpu-gles/src/gpu/gles/GLESBackend.cpp index 8c843c1ce3..b277889771 100644 --- a/libraries/gpu-gles/src/gpu/gles/GLESBackend.cpp +++ b/libraries/gpu-gles/src/gpu/gles/GLESBackend.cpp @@ -166,8 +166,7 @@ void GLESBackend::do_drawIndexedInstanced(const Batch& batch, size_t paramOffset void GLESBackend::do_multiDrawIndirect(const Batch& batch, size_t paramOffset) { #if (GPU_INPUT_PROFILE == GPU_CORE_43) uint commandCount = batch._params[paramOffset + 0]._uint; - GLenum mode = gl::PRIMITIVE_TO_GL[(Primitive)batch._params[paramOffset + 1]._uint]; - + //GLenum mode = gl::PRIMITIVE_TO_GL[(Primitive)batch._params[paramOffset + 1]._uint]; //glMultiDrawArraysIndirect(mode, reinterpret_cast(_input._indirectBufferOffset), commandCount, (GLsizei)_input._indirectBufferStride); qDebug() << "TODO: GLESBackend.cpp:do_multiDrawIndirect do_multiDrawIndirect"; _stats._DSNumDrawcalls += commandCount; @@ -183,9 +182,8 @@ void GLESBackend::do_multiDrawIndirect(const Batch& batch, size_t paramOffset) { void GLESBackend::do_multiDrawIndexedIndirect(const Batch& batch, size_t paramOffset) { //#if (GPU_INPUT_PROFILE == GPU_CORE_43) uint commandCount = batch._params[paramOffset + 0]._uint; - GLenum mode = gl::PRIMITIVE_TO_GL[(Primitive)batch._params[paramOffset + 1]._uint]; - GLenum indexType = gl::ELEMENT_TYPE_TO_GL[_input._indexBufferType]; - + //GLenum mode = gl::PRIMITIVE_TO_GL[(Primitive)batch._params[paramOffset + 1]._uint]; + //GLenum indexType = gl::ELEMENT_TYPE_TO_GL[_input._indexBufferType]; //glMultiDrawElementsIndirect(mode, indexType, reinterpret_cast(_input._indirectBufferOffset), commandCount, (GLsizei)_input._indirectBufferStride); qDebug() << "TODO: GLESBackend.cpp:do_multiDrawIndexedIndirect glMultiDrawElementsIndirect"; _stats._DSNumDrawcalls += commandCount; diff --git a/libraries/gpu-gles/src/gpu/gles/GLESBackendOutput.cpp b/libraries/gpu-gles/src/gpu/gles/GLESBackendOutput.cpp index 8bf9267fde..7dab3bc684 100644 --- a/libraries/gpu-gles/src/gpu/gles/GLESBackendOutput.cpp +++ b/libraries/gpu-gles/src/gpu/gles/GLESBackendOutput.cpp @@ -99,7 +99,8 @@ public: if (!_colorBuffers.empty()) { glDrawBuffers((GLsizei)_colorBuffers.size(), _colorBuffers.data()); } else { - glDrawBuffers(1, {GL_NONE}); + static const std::vector NO_BUFFERS{ GL_NONE }; + glDrawBuffers((GLsizei)NO_BUFFERS.size(), NO_BUFFERS.data()); } // Now check for completness diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 30121a232d..c437a8c556 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -211,6 +211,6 @@ void CauterizedModel::updateRenderItems() { } const Model::MeshState& CauterizedModel::getCauterizeMeshState(int index) const { - assert(index < _meshStates.size()); + assert((size_t)index < _meshStates.size()); return _cauterizeMeshStates.at(index); } diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index ba705e56cb..bf2dce85e8 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -180,7 +180,7 @@ LightStage::LightPointer LightStage::removeLight(Index index) { _lightMap.erase(removedLight); _descs[index] = Desc(); } - assert(_descs.size() <= index || _descs[index].shadowId == INVALID_INDEX); + assert(_descs.size() <= (size_t)index || _descs[index].shadowId == INVALID_INDEX); return removedLight; } From 101d6763ccd9c0aad88643a86b44288c0e4eb4a4 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 29 Nov 2017 09:11:52 -0800 Subject: [PATCH 26/30] PR feedback --- android/app/src/main/cpp/native-lib.cpp | 7 +- android/app/src/main/cpp/renderer.cpp | 471 +----------------- android/app/src/main/cpp/renderer.h | 47 +- .../saintandreas/testapp/MainActivity.java | 19 +- .../src/gpu/gles/GLESBackendOutput.cpp | 2 +- 5 files changed, 31 insertions(+), 515 deletions(-) diff --git a/android/app/src/main/cpp/native-lib.cpp b/android/app/src/main/cpp/native-lib.cpp index 156d43d849..fe21a250de 100644 --- a/android/app/src/main/cpp/native-lib.cpp +++ b/android/app/src/main/cpp/native-lib.cpp @@ -37,12 +37,7 @@ extern "C" { JNI_METHOD(jlong, nativeCreateRenderer) (JNIEnv *env, jclass clazz, jobject class_loader, jobject android_context, jlong native_gvr_api) { qInstallMessageHandler(messageHandler); -#if defined(GVR) - auto gvrContext = reinterpret_cast(native_gvr_api); - return toJni(new NativeRenderer(gvrContext)); -#else - return toJni(new NativeRenderer(nullptr)); -#endif + return toJni(new NativeRenderer()); } JNI_METHOD(void, nativeDestroyRenderer) diff --git a/android/app/src/main/cpp/renderer.cpp b/android/app/src/main/cpp/renderer.cpp index 27e4a7d882..3b23b7e187 100644 --- a/android/app/src/main/cpp/renderer.cpp +++ b/android/app/src/main/cpp/renderer.cpp @@ -1,119 +1,14 @@ #include "renderer.h" #include +#include #include #include #include -#include - -#if 0 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -#if defined(GVR) -#include -#include "GoogleVRHelpers.h" - -static const uint64_t kPredictionTimeWithoutVsyncNanos = 50000000; -static const gvr_rectf fullscreen = {0, 1, 0, 1}; - -template -void withFrameBuffer(gvr::Frame& frame, int32_t index, F f) { - frame.BindBuffer(index); - f(); - frame.Unbind(); -} - -std::array buildViewports(const std::unique_ptr &gvrapi) { - return { {gvrapi->CreateBufferViewport(), gvrapi->CreateBufferViewport()} }; -} - -// Computes a texture size that has approximately half as many pixels. This is -// equivalent to scaling each dimension by approximately sqrt(2)/2. -static gvr::Sizei HalfPixelCount(const gvr::Sizei &in) { - // Scale each dimension by sqrt(2)/2 ~= 7/10ths. - gvr::Sizei out; - out.width = (7 * in.width) / 10; - out.height = (7 * in.height) / 10; - return out; -} - -void testShaderBuild(const char* vs_src, const char * fs_src) { - std::string error; - GLuint vs, fs; - if (!gl::compileShader(GL_VERTEX_SHADER, vs_src, VERTEX_SHADER_DEFINES, vs, error) || - !gl::compileShader(GL_FRAGMENT_SHADER, fs_src, PIXEL_SHADER_DEFINES, fs, error)) { - throw std::runtime_error("Failed to compile shader"); - } - auto pr = gl::compileProgram({ vs, fs }, error); - if (!pr) { - throw std::runtime_error("Failed to link shader"); - } -} - -#endif - -static const float kZNear = 1.0f; -static const float kZFar = 100.0f; - -static const char *kSimepleVertexShader = R"glsl( -#version 300 es +static const char *kSimepleVertexShader = R"glsl(#version 300 es #extension GL_OVR_multiview2 : enable layout(num_views=2) in; @@ -128,8 +23,7 @@ void main() { } )glsl"; -static const char *kPassthroughFragmentShader = R"glsl( -#version 300 es +static const char *kPassthroughFragmentShader = R"glsl(#version 300 es precision mediump float; in vec4 v_Color; out vec4 FragColor; @@ -137,6 +31,17 @@ out vec4 FragColor; void main() { FragColor = v_Color; } )glsl"; + +int LoadGLShader(int type, const char *shadercode) { + GLuint result = 0; + std::string shaderError; + static const std::string SHADER_DEFINES; + if (!gl::compileShader(type, shadercode, SHADER_DEFINES, result, shaderError)) { + qWarning() << "QQQ" << __FUNCTION__ << "Shader compile failure" << shaderError.c_str(); + } + return result; +} + static void CheckGLError(const char* label) { int gl_error = glGetError(); if (gl_error != GL_NO_ERROR) { @@ -147,160 +52,6 @@ static void CheckGLError(const char* label) { } // Contains vertex, normal and other data. -#if 0 -namespace cube { - const std::array CUBE_COORDS{{ - // Front face - -1.0f, 1.0f, 1.0f, - -1.0f, -1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - -1.0f, -1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - - // Right face - 1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, - 1.0f, 1.0f, -1.0f, - 1.0f, -1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, - 1.0f, 1.0f, -1.0f, - - // Back face - 1.0f, 1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, - -1.0f, 1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, - -1.0f, -1.0f, -1.0f, - -1.0f, 1.0f, -1.0f, - - // Left face - -1.0f, 1.0f, -1.0f, - -1.0f, -1.0f, -1.0f, - -1.0f, 1.0f, 1.0f, - -1.0f, -1.0f, -1.0f, - -1.0f, -1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, - - // Top face - -1.0f, 1.0f, -1.0f, - -1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, -1.0f, - -1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, -1.0f, - - // Bottom face - 1.0f, -1.0f, -1.0f, - 1.0f, -1.0f, 1.0f, - -1.0f, -1.0f, -1.0f, - 1.0f, -1.0f, 1.0f, - -1.0f, -1.0f, 1.0f, - -1.0f, -1.0f, -1.0f - }}; - - const std::array CUBE_COLORS{{ - // front, green - 0.0f, 0.5273f, 0.2656f, - 0.0f, 0.5273f, 0.2656f, - 0.0f, 0.5273f, 0.2656f, - 0.0f, 0.5273f, 0.2656f, - 0.0f, 0.5273f, 0.2656f, - 0.0f, 0.5273f, 0.2656f, - - // right, blue - 0.0f, 0.3398f, 0.9023f, - 0.0f, 0.3398f, 0.9023f, - 0.0f, 0.3398f, 0.9023f, - 0.0f, 0.3398f, 0.9023f, - 0.0f, 0.3398f, 0.9023f, - 0.0f, 0.3398f, 0.9023f, - - // back, also green - 0.0f, 0.5273f, 0.2656f, - 0.0f, 0.5273f, 0.2656f, - 0.0f, 0.5273f, 0.2656f, - 0.0f, 0.5273f, 0.2656f, - 0.0f, 0.5273f, 0.2656f, - 0.0f, 0.5273f, 0.2656f, - - // left, also blue - 0.0f, 0.3398f, 0.9023f, - 0.0f, 0.3398f, 0.9023f, - 0.0f, 0.3398f, 0.9023f, - 0.0f, 0.3398f, 0.9023f, - 0.0f, 0.3398f, 0.9023f, - 0.0f, 0.3398f, 0.9023f, - - // top, red - 0.8359375f, 0.17578125f, 0.125f, - 0.8359375f, 0.17578125f, 0.125f, - 0.8359375f, 0.17578125f, 0.125f, - 0.8359375f, 0.17578125f, 0.125f, - 0.8359375f, 0.17578125f, 0.125f, - 0.8359375f, 0.17578125f, 0.125f, - - // bottom, also red - 0.8359375f, 0.17578125f, 0.125f, - 0.8359375f, 0.17578125f, 0.125f, - 0.8359375f, 0.17578125f, 0.125f, - 0.8359375f, 0.17578125f, 0.125f, - 0.8359375f, 0.17578125f, 0.125f, - 0.8359375f, 0.17578125f, 0.125f - }}; - - const std::array CUBE_NORMALS{{ - // Front face - 0.0f, 0.0f, 1.0f, - 0.0f, 0.0f, 1.0f, - 0.0f, 0.0f, 1.0f, - 0.0f, 0.0f, 1.0f, - 0.0f, 0.0f, 1.0f, - 0.0f, 0.0f, 1.0f, - - // Right face - 1.0f, 0.0f, 0.0f, - 1.0f, 0.0f, 0.0f, - 1.0f, 0.0f, 0.0f, - 1.0f, 0.0f, 0.0f, - 1.0f, 0.0f, 0.0f, - 1.0f, 0.0f, 0.0f, - - // Back face - 0.0f, 0.0f, -1.0f, - 0.0f, 0.0f, -1.0f, - 0.0f, 0.0f, -1.0f, - 0.0f, 0.0f, -1.0f, - 0.0f, 0.0f, -1.0f, - 0.0f, 0.0f, -1.0f, - - // Left face - -1.0f, 0.0f, 0.0f, - -1.0f, 0.0f, 0.0f, - -1.0f, 0.0f, 0.0f, - -1.0f, 0.0f, 0.0f, - -1.0f, 0.0f, 0.0f, - -1.0f, 0.0f, 0.0f, - - // Top face - 0.0f, 1.0f, 0.0f, - 0.0f, 1.0f, 0.0f, - 0.0f, 1.0f, 0.0f, - 0.0f, 1.0f, 0.0f, - 0.0f, 1.0f, 0.0f, - 0.0f, 1.0f, 0.0f, - - // Bottom face - 0.0f, -1.0f, 0.0f, - 0.0f, -1.0f, 0.0f, - 0.0f, -1.0f, 0.0f, - 0.0f, -1.0f, 0.0f, - 0.0f, -1.0f, 0.0f, - 0.0f, -1.0f, 0.0f - }}; -} -#endif - namespace triangle { static std::array TRIANGLE_VERTS {{ -0.5f, -0.5f, 0.0f, @@ -309,103 +60,8 @@ namespace triangle { }}; } -const std::string VERTEX_SHADER_DEFINES{ R"GLSL( -#version 300 es -#extension GL_EXT_clip_cull_distance : enable -#define GPU_VERTEX_SHADER -#define GPU_SSBO_TRANSFORM_OBJECT 1 -#define GPU_TRANSFORM_IS_STEREO -#define GPU_TRANSFORM_STEREO_CAMERA -#define GPU_TRANSFORM_STEREO_CAMERA_INSTANCED -#define GPU_TRANSFORM_STEREO_SPLIT_SCREEN -)GLSL" }; - -const std::string PIXEL_SHADER_DEFINES{ R"GLSL( -#version 300 es -precision mediump float; -#define GPU_PIXEL_SHADER -#define GPU_TRANSFORM_IS_STEREO -#define GPU_TRANSFORM_STEREO_CAMERA -#define GPU_TRANSFORM_STEREO_CAMERA_INSTANCED -#define GPU_TRANSFORM_STEREO_SPLIT_SCREEN -)GLSL" }; - - -#if defined(GVR) -NativeRenderer::NativeRenderer(gvr_context *vrContext) : - _gvrapi(new gvr::GvrApi(vrContext, false)), - _viewports(buildViewports(_gvrapi)), - _gvr_viewer_type(_gvrapi->GetViewerType()) -{ - start = std::chrono::system_clock::now(); -} - -void NativeRenderer::InitializeVR() { - _gvrapi->InitializeGl(); - bool multiviewEnabled = _gvrapi->IsFeatureSupported(GVR_FEATURE_MULTIVIEW); - qWarning() << "QQQ" << __FUNCTION__ << "Multiview enabled " << multiviewEnabled; - // Because we are using 2X MSAA, we can render to half as many pixels and - // achieve similar quality. - _renderSize = HalfPixelCount(_gvrapi->GetMaximumEffectiveRenderTargetSize()); - - std::vector specs; - specs.push_back(_gvrapi->CreateBufferSpec()); - specs[0].SetColorFormat(GVR_COLOR_FORMAT_RGBA_8888); - specs[0].SetDepthStencilFormat(GVR_DEPTH_STENCIL_FORMAT_DEPTH_16); - specs[0].SetSamples(2); - gvr::Sizei half_size = {_renderSize.width / 2, _renderSize.height}; - specs[0].SetMultiviewLayers(2); - specs[0].SetSize(half_size); - - _swapchain.reset(new gvr::SwapChain(_gvrapi->CreateSwapChain(specs))); - _viewportlist.reset(new gvr::BufferViewportList(_gvrapi->CreateEmptyBufferViewportList())); -} - -void NativeRenderer::PrepareFramebuffer() { - const gvr::Sizei recommended_size = HalfPixelCount( - _gvrapi->GetMaximumEffectiveRenderTargetSize()); - if (_renderSize.width != recommended_size.width || - _renderSize.height != recommended_size.height) { - // We need to resize the framebuffer. Note that multiview uses two texture - // layers, each with half the render width. - gvr::Sizei framebuffer_size = recommended_size; - framebuffer_size.width /= 2; - _swapchain->ResizeBuffer(0, framebuffer_size); - _renderSize = recommended_size; - } -} -#else -NativeRenderer::NativeRenderer(void *vrContext) -{ - start = std::chrono::system_clock::now(); -} -#endif - - -/** - * Converts a raw text file, saved as a resource, into an OpenGL ES shader. - * - * @param type The type of shader we will be creating. - * @param resId The resource ID of the raw text file. - * @return The shader object handler. - */ -int LoadGLShader(int type, const char *shadercode) { - GLuint result = 0; - std::string shaderError; - static const std::string SHADER_DEFINES; - if (!gl::compileShader(type, shadercode, SHADER_DEFINES, result, shaderError)) { - qWarning() << "QQQ" << __FUNCTION__ << "Shader compile failure" << shaderError.c_str(); - } - return result; -} void NativeRenderer::InitializeGl() { - qDebug() << "QQQ" << __FUNCTION__; - -#if defined(GVR) - InitializeVR(); -#endif - glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glDisable(GL_SCISSOR_TEST); @@ -414,35 +70,21 @@ void NativeRenderer::InitializeGl() { const uint32_t vertShader = LoadGLShader(GL_VERTEX_SHADER, kSimepleVertexShader); const uint32_t fragShader = LoadGLShader(GL_FRAGMENT_SHADER, kPassthroughFragmentShader); std::string error; - _cubeProgram = gl::compileProgram({ vertShader, fragShader }, error); + _program = gl::compileProgram({ vertShader, fragShader }, error); CheckGLError("build program"); - glGenBuffers(1, &_cubeBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _cubeBuffer); + glGenBuffers(1, &_geometryBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _geometryBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 9, triangle::TRIANGLE_VERTS.data(), GL_STATIC_DRAW); - /* - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 108 * 3, NULL, GL_STATIC_DRAW); - glBufferSubData(GL_ARRAY_BUFFER, sizeof(float) * 108 * 0, sizeof(float) * 108, cube::CUBE_COORDS.data()); - glBufferSubData(GL_ARRAY_BUFFER, sizeof(float) * 108 * 1, sizeof(float) * 108, cube::CUBE_COLORS.data()); - glBufferSubData(GL_ARRAY_BUFFER, sizeof(float) * 108 * 2, sizeof(float) * 108, cube::CUBE_NORMALS.data()); - */ glBindBuffer(GL_ARRAY_BUFFER, 0); CheckGLError("upload vertices"); - glGenVertexArrays(1, &_cubeVao); - glBindBuffer(GL_ARRAY_BUFFER, _cubeBuffer); - glBindVertexArray(_cubeVao); + glGenVertexArrays(1, &_vao); + glBindBuffer(GL_ARRAY_BUFFER, _geometryBuffer); + glBindVertexArray(_vao); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); - /* - glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0); - glEnableVertexAttribArray(0); - glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, (const void*)(sizeof(float) * 108 * 1) ); - glEnableVertexAttribArray(1); - glVertexAttribPointer(2, 3, GL_FLOAT, false, 0, (const void*)(sizeof(float) * 108 * 2)); - glEnableVertexAttribArray(2); - */ glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); CheckGLError("build vao "); @@ -457,72 +99,12 @@ void NativeRenderer::DrawFrame() { v.g = 1.0f - v.r; v.b = 1.0f; -#if defined(GVR) - PrepareFramebuffer(); - - // A client app does its rendering here. - gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); - target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; - - using namespace googlevr; - using namespace bilateral; - const auto gvrHeadPose = _gvrapi->GetHeadSpaceFromStartSpaceRotation(target_time); - _head_view = toGlm(gvrHeadPose); - _viewportlist->SetToRecommendedBufferViewports(); - - - glm::mat4 eye_views[2]; - for_each_side([&](bilateral::Side side) { - int eye = index(side); - const gvr::Eye gvr_eye = eye == 0 ? GVR_LEFT_EYE : GVR_RIGHT_EYE; - const auto& eyeView = eye_views[eye] = toGlm(_gvrapi->GetEyeFromHeadMatrix(gvr_eye)) * _head_view; - auto& viewport = _viewports[eye]; - - _viewportlist->GetBufferViewport(eye, &viewport); - viewport.SetSourceUv(fullscreen); - viewport.SetSourceLayer(eye); - _viewportlist->SetBufferViewport(eye, viewport); - const auto &mvc = _modelview_cube[eye] = eyeView * _model_cube; - const auto &mvf = _modelview_floor[eye] = eyeView * _model_floor; - const gvr_rectf fov = viewport.GetSourceFov(); - const glm::mat4 perspective = perspectiveMatrixFromView(fov, kZNear, kZFar); - _modelview_projection_cube[eye] = perspective * mvc; - _modelview_projection_floor[eye] = perspective * mvf; - _light_pos_eye_space[eye] = glm::vec3(eyeView * _light_pos_world_space); - }); - - - gvr::Frame frame = _swapchain->AcquireFrame(); - withFrameBuffer(frame, 0, [&]{ - glClearColor(v.r, v.g, v.b, 1); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glViewport(0, 0, _renderSize.width / 2, _renderSize.height); - glUseProgram(_cubeProgram); - glBindVertexArray(_cubeVao); - glDrawArrays(GL_TRIANGLES, 0, 3); - glBindVertexArray(0); - }); - - frame.Submit(*_viewportlist, gvrHeadPose); - CheckGLError("onDrawFrame"); -#else - constexpr size_t eye = 0; - const glm::mat4 eyeView{ 1 }; - const auto &mvc = _modelview_cube[eye] = eyeView * _model_cube; - const auto &mvf = _modelview_floor[eye] = eyeView * _model_floor; - const glm::mat4 perspective = glm::perspective(60.0f, 1.0f, kZNear, kZFar); - _modelview_projection_cube[eye] = perspective * mvc; - _modelview_projection_floor[eye] = perspective * mvf; - _light_pos_eye_space[eye] = glm::vec3(eyeView * _light_pos_world_space); - - glClearColor(v.r, v.g, v.b, 1); + glClearColor(v.r, v.g, v.b, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - //glViewport(0, 0, _renderSize.width / 2, _renderSize.height); - glUseProgram(_cubeProgram); - glBindVertexArray(_cubeVao); + glUseProgram(_program); + glBindVertexArray(_vao); glDrawArrays(GL_TRIANGLES, 0, 3); glBindVertexArray(0); -#endif } void NativeRenderer::OnTriggerEvent() { @@ -531,15 +113,8 @@ void NativeRenderer::OnTriggerEvent() { void NativeRenderer::OnPause() { qDebug() << "QQQ" << __FUNCTION__; -#if defined(GVR) - _gvrapi->PauseTracking(); -#endif } void NativeRenderer::OnResume() { qDebug() << "QQQ" << __FUNCTION__; -#if defined(GVR) - _gvrapi->ResumeTracking(); - _gvrapi->RefreshViewerProfile(); -#endif } diff --git a/android/app/src/main/cpp/renderer.h b/android/app/src/main/cpp/renderer.h index 07294f3dc1..522f672e3b 100644 --- a/android/app/src/main/cpp/renderer.h +++ b/android/app/src/main/cpp/renderer.h @@ -4,21 +4,8 @@ #include #include -//#define GVR - -#if defined(GVR) -#include -#endif - class NativeRenderer { public: - -#if defined(GVR) - NativeRenderer(gvr_context* vrContext); -#else - NativeRenderer(void* vrContext); -#endif - void InitializeGl(); void DrawFrame(); void OnTriggerEvent(); @@ -26,35 +13,9 @@ public: void OnResume(); private: + std::chrono::time_point start { std::chrono::system_clock::now() }; - - std::chrono::time_point start; -#if defined(GVR) - void InitializeVR(); - void PrepareFramebuffer(); - - std::unique_ptr _gvrapi; - gvr::ViewerType _gvr_viewer_type; - std::unique_ptr _viewportlist; - std::unique_ptr _swapchain; - std::array _viewports; - gvr::Sizei _renderSize; -#endif - - uint32_t _cubeBuffer { 0 }; - uint32_t _cubeVao { 0 }; - uint32_t _cubeProgram { 0 }; - - glm::mat4 _head_view; - glm::mat4 _model_cube; - glm::mat4 _camera; - glm::mat4 _view; - glm::mat4 _model_floor; - - std::array _modelview_cube; - std::array _modelview_floor; - std::array _modelview_projection_cube; - std::array _modelview_projection_floor; - std::array _light_pos_eye_space; - const glm::vec4 _light_pos_world_space{ 0, 2, 0, 1}; + uint32_t _geometryBuffer { 0 }; + uint32_t _vao { 0 }; + uint32_t _program { 0 }; }; diff --git a/android/app/src/main/java/org/saintandreas/testapp/MainActivity.java b/android/app/src/main/java/org/saintandreas/testapp/MainActivity.java index 783c3f4483..65e6c394e7 100644 --- a/android/app/src/main/java/org/saintandreas/testapp/MainActivity.java +++ b/android/app/src/main/java/org/saintandreas/testapp/MainActivity.java @@ -26,10 +26,9 @@ public class MainActivity extends Activity { } private long nativeRenderer; - //private GvrLayout gvrLayout; private GLSurfaceView surfaceView; - private native long nativeCreateRenderer(ClassLoader appClassLoader, Context context, long nativeGvrContext); + private native long nativeCreateRenderer(ClassLoader appClassLoader, Context context); private native void nativeDestroyRenderer(long renderer); private native void nativeInitializeGl(long renderer); private native void nativeDrawFrame(long renderer); @@ -55,33 +54,21 @@ public class MainActivity extends Activity { if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { setImmersiveSticky(); } }); - // gvrLayout = new GvrLayout(this); nativeRenderer = nativeCreateRenderer( getClass().getClassLoader(), - getApplicationContext(), - 0); - //gvrLayout.getGvrApi().getNativeGvrContext()); + getApplicationContext()); surfaceView = new GLSurfaceView(this); surfaceView.setEGLContextClientVersion(3); surfaceView.setEGLConfigChooser(8, 8, 8, 0, 0, 0); surfaceView.setPreserveEGLContextOnPause(true); surfaceView.setRenderer(new NativeRenderer()); - -// gvrLayout.setPresentationView(surfaceView); -// setContentView(gvrLayout); -// if (gvrLayout.setAsyncReprojectionEnabled(true)) { -// AndroidCompat.setSustainedPerformanceMode(this, true); -// } -// AndroidCompat.setVrModeEnabled(this, true); - setContentView(surfaceView); } @Override protected void onDestroy() { super.onDestroy(); - //gvrLayout.shutdown(); nativeDestroyRenderer(nativeRenderer); nativeRenderer = 0; } @@ -90,14 +77,12 @@ public class MainActivity extends Activity { protected void onPause() { surfaceView.queueEvent(()->nativeOnPause(nativeRenderer)); surfaceView.onPause(); -// gvrLayout.onPause(); super.onPause(); } @Override protected void onResume() { super.onResume(); -// gvrLayout.onResume(); surfaceView.onResume(); surfaceView.queueEvent(()->nativeOnResume(nativeRenderer)); } diff --git a/libraries/gpu-gles/src/gpu/gles/GLESBackendOutput.cpp b/libraries/gpu-gles/src/gpu/gles/GLESBackendOutput.cpp index 7dab3bc684..0b7c525fbb 100644 --- a/libraries/gpu-gles/src/gpu/gles/GLESBackendOutput.cpp +++ b/libraries/gpu-gles/src/gpu/gles/GLESBackendOutput.cpp @@ -99,7 +99,7 @@ public: if (!_colorBuffers.empty()) { glDrawBuffers((GLsizei)_colorBuffers.size(), _colorBuffers.data()); } else { - static const std::vector NO_BUFFERS{ GL_NONE }; + static const std::vector NO_BUFFERS{ GL_NONE }; glDrawBuffers((GLsizei)NO_BUFFERS.size(), NO_BUFFERS.data()); } From 55589312f13bec1ab2ae12e332097883d3ea7921 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 29 Nov 2017 09:53:48 -0800 Subject: [PATCH 27/30] new padding/initialization that matters on linux server --- interface/src/commerce/Wallet.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index d6190aa7a0..d4611d3e9a 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -166,7 +166,7 @@ bool writeKeys(const char* filename, EC_KEY* keys) { } QPair generateECKeypair() { - + EC_KEY* keyPair = EC_KEY_new_by_curve_name(NID_secp256k1); QPair retval; EC_KEY_set_asn1_flag(keyPair, OPENSSL_EC_NAMED_CURVE); @@ -212,8 +212,8 @@ QPair generateECKeypair() { // prepare the return values. TODO: Fix this - we probably don't really even want the // private key at all (better to read it when we need it?). Or maybe we do, when we have // multiple keys? - retval.first = new QByteArray(reinterpret_cast(publicKeyDER), publicKeyLength ), - retval.second = new QByteArray(reinterpret_cast(privateKeyDER), privateKeyLength ); + retval.first = new QByteArray(reinterpret_cast(publicKeyDER), publicKeyLength); + retval.second = new QByteArray(reinterpret_cast(privateKeyDER), privateKeyLength); // cleanup the publicKeyDER and publicKeyDER data OPENSSL_free(publicKeyDER); @@ -255,7 +255,7 @@ QByteArray readPublicKey(const char* filename) { } // the private key should be read/copied into heap memory. For now, we need the EC_KEY struct -// so I'll return that. +// so I'll return that. EC_KEY* readPrivateKey(const char* filename) { FILE* fp; EC_KEY* key = NULL; @@ -540,20 +540,21 @@ QString Wallet::signWithKey(const QByteArray& text, const QString& key) { qCInfo(commerce) << "Signing text" << text << "with key" << key; EC_KEY* ecPrivateKey = NULL; if ((ecPrivateKey = readPrivateKey(keyFilePath().toStdString().c_str()))) { - QByteArray signature(ECDSA_size(ecPrivateKey), 0); + unsigned char* sig = new unsigned char[ECDSA_size(ecPrivateKey)]; + unsigned int signatureBytes = 0; QByteArray hashedPlaintext = QCryptographicHash::hash(text, QCryptographicHash::Sha256); - int retrn = ECDSA_sign(0, - reinterpret_cast(hashedPlaintext.constData()), + int retrn = ECDSA_sign(0, + reinterpret_cast(hashedPlaintext.constData()), hashedPlaintext.size(), - reinterpret_cast(signature.data()), + sig, &signatureBytes, ecPrivateKey); EC_KEY_free(ecPrivateKey); - + QByteArray signature(reinterpret_cast(sig), signatureBytes); if (retrn != -1) { return signature.toBase64(); } @@ -733,11 +734,11 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack qCDebug(commerce) << "During entity ownership challenge, creating the EC-signed nonce failed."; status = -1; } - + EC_KEY_free(ec); QByteArray ba = sig.toLocal8Bit(); const char *sigChar = ba.data(); - + QByteArray textByteArray; if (status > -1) { textByteArray = QByteArray(sigChar, (int) strlen(sigChar)); @@ -801,4 +802,4 @@ void Wallet::getWalletStatus() { walletScriptingInterface->setWalletStatus(status); return; } -} \ No newline at end of file +} From fb038c17ee27fd563685d0f46b37a77bdbf3d0ca Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 29 Nov 2017 09:54:34 -0800 Subject: [PATCH 28/30] for now, point this PR at staging so that it can be tested as built by jenkins --- libraries/networking/src/NetworkingConstants.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/NetworkingConstants.h b/libraries/networking/src/NetworkingConstants.h index 0c210e4360..1edd842958 100644 --- a/libraries/networking/src/NetworkingConstants.h +++ b/libraries/networking/src/NetworkingConstants.h @@ -20,7 +20,7 @@ namespace NetworkingConstants { // \domain-server\resources\web\js\shared.js const QUrl METAVERSE_SERVER_URL_STABLE("https://metaverse.highfidelity.com"); const QUrl METAVERSE_SERVER_URL_STAGING("https://staging.highfidelity.com"); - const QUrl METAVERSE_SERVER_URL = METAVERSE_SERVER_URL_STABLE; + const QUrl METAVERSE_SERVER_URL = METAVERSE_SERVER_URL_STAGING; } #endif // hifi_NetworkingConstants_h From 115bc27557911eebb7a335a63195fad8d71a466c Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 29 Nov 2017 13:39:58 -0800 Subject: [PATCH 29/30] back to stable, rather than staging --- libraries/networking/src/NetworkingConstants.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/NetworkingConstants.h b/libraries/networking/src/NetworkingConstants.h index 1edd842958..0c210e4360 100644 --- a/libraries/networking/src/NetworkingConstants.h +++ b/libraries/networking/src/NetworkingConstants.h @@ -20,7 +20,7 @@ namespace NetworkingConstants { // \domain-server\resources\web\js\shared.js const QUrl METAVERSE_SERVER_URL_STABLE("https://metaverse.highfidelity.com"); const QUrl METAVERSE_SERVER_URL_STAGING("https://staging.highfidelity.com"); - const QUrl METAVERSE_SERVER_URL = METAVERSE_SERVER_URL_STAGING; + const QUrl METAVERSE_SERVER_URL = METAVERSE_SERVER_URL_STABLE; } #endif // hifi_NetworkingConstants_h From 57ec73bb13675cdbf928871e83e293eb8a2ae516 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 29 Nov 2017 14:37:20 -0800 Subject: [PATCH 30/30] spacing --- libraries/entities/src/EntityItemProperties.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 6ec5e8eb05..5ab4bdee01 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -2553,8 +2553,7 @@ bool EntityItemProperties::verifySignature(const QString& publicKey, const QByte EVP_PKEY_free(evp_key); } return answer; - } - else { + } else { if (bio) { BIO_free(bio); } @@ -2566,8 +2565,7 @@ bool EntityItemProperties::verifySignature(const QString& publicKey, const QByte qCWarning(entities) << "Failed to verify signature! key" << publicKey << " EC key error:" << error_str; return false; } - } - else { + } else { if (bio) { BIO_free(bio); }