Merge branch 'master' of https://github.com/highfidelity/hifi into context-overlays

This commit is contained in:
Zach Fox 2017-07-26 14:11:03 -07:00
commit 1e80736718
13 changed files with 109 additions and 56 deletions

View file

@ -1,4 +1,8 @@
cmake_minimum_required(VERSION 3.2)
if (WIN32)
cmake_minimum_required(VERSION 3.7)
else()
cmake_minimum_required(VERSION 3.2)
endif()
if (USE_ANDROID_TOOLCHAIN)
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/android/android.toolchain.cmake")
@ -33,6 +37,10 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
find_package( Threads )
if (WIN32)
if (NOT "${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
message( FATAL_ERROR "Only 64 bit builds supported." )
endif()
add_definitions(-DNOMINMAX -D_CRT_SECURE_NO_WARNINGS)
if (NOT WINDOW_SDK_PATH)
@ -41,16 +49,13 @@ if (WIN32)
# sets path for Microsoft SDKs
# if you get build error about missing 'glu32' this path is likely wrong
if (MSVC10)
set(WINDOW_SDK_PATH "C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1 " CACHE PATH "Windows SDK PATH")
elseif (MSVC12)
if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
set(WINDOW_SDK_FOLDER "x64")
else()
set(WINDOW_SDK_FOLDER "x86")
endif()
if (MSVC_VERSION GREATER_EQUAL 1910) # VS 2017
set(WINDOW_SDK_PATH "C:/Program Files (x86)/Windows Kits/10/Lib/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/x64" CACHE PATH "Windows SDK PATH")
elseif (MSVC_VERSION GREATER_EQUAL 1800) # VS 2013
set(WINDOW_SDK_PATH "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\${WINDOW_SDK_FOLDER}" CACHE PATH "Windows SDK PATH")
endif ()
else()
message( FATAL_ERROR "Visual Studio 2013 or higher required." )
endif()
if (DEBUG_DISCOVERED_SDK_PATH)
message(STATUS "The discovered Windows SDK path is ${WINDOW_SDK_PATH}")
@ -103,7 +108,7 @@ else ()
endif ()
if (APPLE)
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++0x")
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11")
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --stdlib=libc++")
endif ()

View file

@ -21,8 +21,8 @@ endif ()
ExternalProject_Add(
${EXTERNAL_NAME}
URL https://s3-us-west-1.amazonaws.com/hifi-production/dependencies/quazip-0.7.2.zip
URL_MD5 2955176048a31262c09259ca8d309d19
URL https://hifi-public.s3.amazonaws.com/dependencies/quazip-0.7.3.zip
URL_MD5 ed03754d39b9da1775771819b8001d45
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
CMAKE_ARGS ${QUAZIP_CMAKE_ARGS}
LOG_DOWNLOAD 1

View file

@ -126,8 +126,14 @@ macro(SET_PACKAGING_PARAMETERS)
# check if we need to find signtool
if (PRODUCTION_BUILD OR PR_BUILD)
find_program(SIGNTOOL_EXECUTABLE signtool PATHS "C:/Program Files (x86)/Windows Kits/8.1" PATH_SUFFIXES "bin/x64")
if (MSVC_VERSION GREATER_EQUAL 1910) # VS 2017
find_program(SIGNTOOL_EXECUTABLE signtool PATHS "C:/Program Files (x86)/Windows Kits/10" PATH_SUFFIXES "bin/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/x64")
elseif (MSVC_VERSION GREATER_EQUAL 1800) # VS 2013
find_program(SIGNTOOL_EXECUTABLE signtool PATHS "C:/Program Files (x86)/Windows Kits/8.1" PATH_SUFFIXES "bin/x64")
else()
message( FATAL_ERROR "Visual Studio 2013 or higher required." )
endif()
if (NOT SIGNTOOL_EXECUTABLE)
message(FATAL_ERROR "Code signing of executables was requested but signtool.exe could not be found.")
endif ()

View file

@ -385,7 +385,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
// user is attempting to prove their identity to us, but we don't have enough information
sendConnectionTokenPacket(username, nodeConnection.senderSockAddr);
// ask for their public key right now to make sure we have it
requestUserPublicKey(username);
requestUserPublicKey(username, true);
getGroupMemberships(username); // optimistically get started on group memberships
#ifdef WANT_DEBUG
qDebug() << "stalling login because we have no username-signature:" << username;
@ -521,7 +521,10 @@ bool DomainGatekeeper::verifyUserSignature(const QString& username,
const HifiSockAddr& senderSockAddr) {
// it's possible this user can be allowed to connect, but we need to check their username signature
auto lowerUsername = username.toLower();
QByteArray publicKeyArray = _userPublicKeys.value(lowerUsername);
KeyFlagPair publicKeyPair = _userPublicKeys.value(lowerUsername);
QByteArray publicKeyArray = publicKeyPair.first;
bool isOptimisticKey = publicKeyPair.second;
const QUuid& connectionToken = _connectionTokenHash.value(lowerUsername);
@ -555,10 +558,16 @@ bool DomainGatekeeper::verifyUserSignature(const QString& username,
return true;
} else {
if (!senderSockAddr.isNull()) {
qDebug() << "Error decrypting username signature for " << username << "- denying connection.";
// we only send back a LoginError if this wasn't an "optimistic" key
// (a key that we hoped would work but is probably stale)
if (!senderSockAddr.isNull() && !isOptimisticKey) {
qDebug() << "Error decrypting username signature for" << username << "- denying connection.";
sendConnectionDeniedPacket("Error decrypting username signature.", senderSockAddr,
DomainHandler::ConnectionRefusedReason::LoginError);
} else if (!senderSockAddr.isNull()) {
qDebug() << "Error decrypting username signature for" << username << "with optimisitic key -"
<< "re-requesting public key and delaying connection";
}
// free up the public key, we don't need it anymore
@ -604,20 +613,7 @@ bool DomainGatekeeper::isWithinMaxCapacity() {
return true;
}
void DomainGatekeeper::preloadAllowedUserPublicKeys() {
QStringList allowedUsers = _server->_settingsManager.getAllNames();
if (allowedUsers.size() > 0) {
// in the future we may need to limit how many requests here - for now assume that lists of allowed users are not
// going to create > 100 requests
foreach(const QString& username, allowedUsers) {
requestUserPublicKey(username);
}
}
}
void DomainGatekeeper::requestUserPublicKey(const QString& username) {
void DomainGatekeeper::requestUserPublicKey(const QString& username, bool isOptimistic) {
// don't request public keys for the standard psuedo-account-names
if (NodePermissions::standardNames.contains(username, Qt::CaseInsensitive)) {
return;
@ -628,7 +624,7 @@ void DomainGatekeeper::requestUserPublicKey(const QString& username) {
// public-key request for this username is already flight, not rerequesting
return;
}
_inFlightPublicKeyRequests += lowerUsername;
_inFlightPublicKeyRequests.insert(lowerUsername, isOptimistic);
// even if we have a public key for them right now, request a new one in case it has just changed
JSONCallbackParameters callbackParams;
@ -640,7 +636,7 @@ void DomainGatekeeper::requestUserPublicKey(const QString& username) {
const QString USER_PUBLIC_KEY_PATH = "api/v1/users/%1/public_key";
qDebug() << "Requesting public key for user" << username;
qDebug().nospace() << "Requesting " << (isOptimistic ? "optimistic " : " ") << "public key for user " << username;
DependencyManager::get<AccountManager>()->sendRequest(USER_PUBLIC_KEY_PATH.arg(username),
AccountManagerAuth::None,
@ -662,16 +658,21 @@ void DomainGatekeeper::publicKeyJSONCallback(QNetworkReply& requestReply) {
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object();
QString username = extractUsernameFromPublicKeyRequest(requestReply);
bool isOptimisticKey = _inFlightPublicKeyRequests.take(username);
if (jsonObject["status"].toString() == "success" && !username.isEmpty()) {
// pull the public key as a QByteArray from this response
const QString JSON_DATA_KEY = "data";
const QString JSON_PUBLIC_KEY_KEY = "public_key";
_userPublicKeys[username.toLower()] =
QByteArray::fromBase64(jsonObject[JSON_DATA_KEY].toObject()[JSON_PUBLIC_KEY_KEY].toString().toUtf8());
}
qDebug().nospace() << "Extracted " << (isOptimisticKey ? "optimistic " : " ") << "public key for " << username.toLower();
_inFlightPublicKeyRequests.remove(username);
_userPublicKeys[username.toLower()] =
{
QByteArray::fromBase64(jsonObject[JSON_DATA_KEY].toObject()[JSON_PUBLIC_KEY_KEY].toString().toUtf8()),
isOptimisticKey
};
}
}
void DomainGatekeeper::publicKeyJSONErrorCallback(QNetworkReply& requestReply) {

View file

@ -39,8 +39,6 @@ public:
const QUuid& walletUUID, const QString& nodeVersion);
QUuid assignmentUUIDForPendingAssignment(const QUuid& tempUUID);
void preloadAllowedUserPublicKeys();
void removeICEPeer(const QUuid& peerUUID) { _icePeers.remove(peerUUID); }
static void sendProtocolMismatchConnectionDenial(const HifiSockAddr& senderSockAddr);
@ -93,7 +91,7 @@ private:
void pingPunchForConnectingPeer(const SharedNetworkPeer& peer);
void requestUserPublicKey(const QString& username);
void requestUserPublicKey(const QString& username, bool isOptimistic = false);
DomainServer* _server;
@ -102,8 +100,17 @@ private:
QHash<QUuid, SharedNetworkPeer> _icePeers;
QHash<QString, QUuid> _connectionTokenHash;
QHash<QString, QByteArray> _userPublicKeys;
QSet<QString> _inFlightPublicKeyRequests; // keep track of which we've already asked for
// the word "optimistic" below is used for keys that we request during user connection before the user has
// had a chance to upload a new public key
// we don't send back user signature decryption errors for those keys so that there isn't a thrasing of key re-generation
// and connection refusal
using KeyFlagPair = QPair<QByteArray, bool>;
QHash<QString, KeyFlagPair> _userPublicKeys; // keep track of keys and flag them as optimistic or not
QHash<QString, bool> _inFlightPublicKeyRequests; // keep track of keys we've asked for (and if it was optimistic)
QSet<QString> _domainOwnerFriends; // keep track of friends of the domain owner
QSet<QString> _inFlightGroupMembershipsRequests; // keep track of which we've already asked for

View file

@ -160,9 +160,7 @@ DomainServer::DomainServer(int argc, char* argv[]) :
getTemporaryName();
}
_gatekeeper.preloadAllowedUserPublicKeys(); // so they can connect on first request
//send signal to DomainMetadata when descriptors changed
// send signal to DomainMetadata when descriptors changed
_metadata = new DomainMetadata(this);
connect(&_settingsManager, &DomainServerSettingsManager::settingsUpdated,
_metadata, &DomainMetadata::descriptorsChanged);

View file

@ -182,7 +182,6 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
EntityPropertyFlags propertyFlags(PROP_LAST_ITEM);
EntityPropertyFlags requestedProperties = getEntityProperties(params);
EntityPropertyFlags propertiesDidntFit = requestedProperties;
// If we are being called for a subsequent pass at appendEntityData() that failed to completely encode this item,
// then our entityTreeElementExtraEncodeData should include data about which properties we need to append.
@ -190,6 +189,8 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
requestedProperties = entityTreeElementExtraEncodeData->entities.value(getEntityItemID());
}
EntityPropertyFlags propertiesDidntFit = requestedProperties;
LevelDetails entityLevel = packetData->startLevel();
quint64 lastEdited = getLastEdited();

View file

@ -95,7 +95,7 @@ void GL41Backend::updateInput() {
// GLenum perLocationStride = strides[bufferNum];
GLenum perLocationStride = attrib._element.getLocationSize();
GLuint stride = (GLuint)strides[bufferNum];
GLuint pointer = (GLuint)(attrib._offset + offsets[bufferNum]);
uintptr_t pointer = (uintptr_t)(attrib._offset + offsets[bufferNum]);
GLboolean isNormalized = attrib._element.isNormalized();
for (size_t locNum = 0; locNum < locationCount; ++locNum) {

View file

@ -327,7 +327,7 @@ void NodeList::sendDomainServerCheckIn() {
<< "but no keypair is present. Waiting for keypair generation to complete.";
accountManager->generateNewUserKeypair();
// don't send the check in packet - wait for the keypair first
// don't send the check in packet - wait for the new public key to be available to the domain-server first
return;
}

View file

@ -92,9 +92,8 @@ FileStorage::FileStorage(const QString& filename) : _file(filename) {
FileStorage::~FileStorage() {
if (_mapped) {
if (!_file.unmap(_mapped)) {
throw std::runtime_error("Unable to unmap file");
}
_file.unmap(_mapped);
_mapped = nullptr;
}
if (_file.isOpen()) {
_file.close();

View file

@ -282,7 +282,7 @@ public:
static const vr::VRTextureBounds_t leftBounds{ 0, 0, 0.5f, 1 };
static const vr::VRTextureBounds_t rightBounds{ 0.5f, 0, 1, 1 };
vr::Texture_t texture{ (void*)_colors[currentColorBuffer], vr::TextureType_OpenGL, vr::ColorSpace_Auto };
vr::Texture_t texture{ (void*)(uintptr_t)_colors[currentColorBuffer], vr::TextureType_OpenGL, vr::ColorSpace_Auto };
vr::VRCompositor()->Submit(vr::Eye_Left, &texture, &leftBounds);
vr::VRCompositor()->Submit(vr::Eye_Right, &texture, &rightBounds);
_plugin._presentRate.increment();
@ -643,7 +643,7 @@ void OpenVrDisplayPlugin::hmdPresent() {
_submitThread->waitForPresent();
} else {
GLuint glTexId = getGLBackend()->getTextureID(_compositeFramebuffer->getRenderBuffer(0));
vr::Texture_t vrTexture { (void*)glTexId, vr::TextureType_OpenGL, vr::ColorSpace_Auto };
vr::Texture_t vrTexture { (void*)(uintptr_t)glTexId, vr::TextureType_OpenGL, vr::ColorSpace_Auto };
vr::VRCompositor()->Submit(vr::Eye_Left, &vrTexture, &OPENVR_TEXTURE_BOUNDS_LEFT);
vr::VRCompositor()->Submit(vr::Eye_Right, &vrTexture, &OPENVR_TEXTURE_BOUNDS_RIGHT);
vr::VRCompositor()->PostPresentHandoff();

View file

@ -129,7 +129,7 @@ void releaseOpenVrSystem() {
#endif
// HACK: workaround openvr crash, call submit with an invalid texture, right before VR_Shutdown.
const GLuint INVALID_GL_TEXTURE_HANDLE = -1;
const void* INVALID_GL_TEXTURE_HANDLE = (void*)(uintptr_t)-1;
vr::Texture_t vrTexture{ (void*)INVALID_GL_TEXTURE_HANDLE, vr::TextureType_OpenGL, vr::ColorSpace_Auto };
static vr::VRTextureBounds_t OPENVR_TEXTURE_BOUNDS_LEFT{ 0, 0, 0.5f, 1 };
static vr::VRTextureBounds_t OPENVR_TEXTURE_BOUNDS_RIGHT{ 0.5f, 0, 1, 1 };

View file

@ -0,0 +1,36 @@
//
// eatable.js
//
// Created by Alan-Michael Moody on 7/24/2017
// Copyright 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 () {
var NOMNOM_SOUND = SoundCache.getSound('http://hifi-content.s3.amazonaws.com/DomainContent/production/audio/vegcrunch.wav');
var _entityID;
this.preload = function (entityID) {
_entityID = entityID;
};
this.collisionWithEntity = function(entityUuid, collisionEntityID, collisionInfo) {
var entity = Entities.getEntityProperties(collisionEntityID, ['userData', 'name']);
var isClone = (entity.name.substring(1).split('-')[0] === 'clone');
var isEatable = (JSON.parse(entity.userData).eatable);
if (isEatable && isClone) {
Audio.playSound(NOMNOM_SOUND, {
position: Entities.getEntityProperties(_entityID, ['position']).position,
volume: 0.2,
localOnly: false
});
Entities.deleteEntity(collisionEntityID);
}
};
});