<commit_before>/*
    Yojimbo Client/Server Network Library.

    Copyright © 2016, The Network Protocol Company, Inc.

    Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

        1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

        2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
           in the documentation and/or other materials provided with the distribution.

        3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived
           from this software without specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
    USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "yojimbo_matcher.h"

#include <mbedtls/config.h>
#include <mbedtls/platform.h>
#include <mbedtls/net.h>
#include <mbedtls/debug.h>
#include <mbedtls/ssl.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/error.h>
#include <mbedtls/certs.h>

#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"

#include "sodium.h"

using namespace rapidjson;

#define SERVER_PORT "8080"
#define SERVER_NAME "localhost"

namespace yojimbo
{
    struct MatcherInternal
    {
        mbedtls_net_context server_fd;
        mbedtls_entropy_context entropy;
        mbedtls_ctr_drbg_context ctr_drbg;
        mbedtls_ssl_context ssl;
        mbedtls_ssl_config conf;
        mbedtls_x509_crt cacert;
    };

    Matcher::Matcher( Allocator & allocator )
    {
        m_allocator = &allocator;
        m_initialized = false;
        m_status = MATCHER_IDLE;
        m_internal = YOJIMBO_NEW( allocator, MatcherInternal );
    }

    Matcher::~Matcher()
    {
        mbedtls_net_free( &m_internal->server_fd );
        mbedtls_x509_crt_free( &m_internal->cacert );
        mbedtls_ssl_free( &m_internal->ssl );
        mbedtls_ssl_config_free( &m_internal->conf );
        mbedtls_ctr_drbg_free( &m_internal->ctr_drbg );
        mbedtls_entropy_free( &m_internal->entropy );

        YOJIMBO_DELETE( *m_allocator, MatcherInternal, m_internal );
    }

    bool Matcher::Initialize()
    {
        const char * pers = "yojimbo_client";

        mbedtls_net_init( &m_internal->server_fd );
        mbedtls_ssl_init( &m_internal->ssl );
        mbedtls_ssl_config_init( &m_internal->conf );
        mbedtls_x509_crt_init( &m_internal->cacert );
        mbedtls_ctr_drbg_init( &m_internal->ctr_drbg );
        mbedtls_entropy_init( &m_internal->entropy );

        int result;

        if ( ( result = mbedtls_ctr_drbg_seed( &m_internal->ctr_drbg, mbedtls_entropy_func, &m_internal->entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 )
        {
            return false;
        }

        if ( mbedtls_x509_crt_parse( &m_internal->cacert, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ) < 0 )
        {
            return false;
        }

        m_initialized = true;

        return true;
    }

    void Matcher::RequestMatch( uint32_t protocolId, uint64_t clientId )
    {
        assert( m_initialized );

        int ret, len;
        uint32_t flags;
        char buf[4*1024];
        char request[1024];

        if ( ( ret = mbedtls_net_connect( &m_internal->server_fd, SERVER_NAME, SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 )
        {
            m_status = MATCHER_FAILED;
            goto cleanup;
        }

        if ( ( ret = mbedtls_ssl_config_defaults( &m_internal->conf,
                        MBEDTLS_SSL_IS_CLIENT,
                        MBEDTLS_SSL_TRANSPORT_STREAM,
                        MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
        {
            m_status = MATCHER_FAILED;
            return;
        }

        mbedtls_ssl_conf_authmode( &m_internal->conf, MBEDTLS_SSL_VERIFY_OPTIONAL );
        mbedtls_ssl_conf_ca_chain( &m_internal->conf, &m_internal->cacert, NULL );
        mbedtls_ssl_conf_rng( &m_internal->conf, mbedtls_ctr_drbg_random, &m_internal->ctr_drbg );

        if( ( ret = mbedtls_ssl_setup( &m_internal->ssl, &m_internal->conf ) ) != 0 )
        {
            m_status = MATCHER_FAILED;
            goto cleanup;
        }

        if ( ( ret = mbedtls_ssl_set_hostname( &m_internal->ssl, "yojimbo" ) ) != 0 )
        {
            m_status = MATCHER_FAILED;
            goto cleanup;
        }

        mbedtls_ssl_set_bio( &m_internal->ssl, &m_internal->server_fd, mbedtls_net_send, mbedtls_net_recv, NULL );

        while ( ( ret = mbedtls_ssl_handshake( &m_internal->ssl ) ) != 0 )
        {
            if ( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
            {
                m_status = MATCHER_FAILED;
                goto cleanup;
            }
        }

        if ( ( flags = mbedtls_ssl_get_verify_result( &m_internal->ssl ) ) != 0 )
        {
            // could not verify certificate (eg. it is self-signed)

            // IMPORTANT: this should be locked down #if YOJIMBO_SECURE
        }

        sprintf( request, "GET /match/%d/%" PRIu64 " HTTP/1.0\r\n\r\n", protocolId, clientId );

        while ( ( ret = mbedtls_ssl_write( &m_internal->ssl, (uint8_t*) request, strlen( request ) ) ) <= 0 )
        {
            if ( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
            {
                m_status = MATCHER_FAILED;
                goto cleanup;
            }
        }

        do
        {
            len = sizeof( buf ) - 1;
            memset( buf, 0, sizeof( buf ) );
            ret = mbedtls_ssl_read( &m_internal->ssl, (uint8_t*) buf, len );

            if ( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE )
                continue;

            if ( ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY )
                break;

            if ( ret <= 0 )
                break;

            const char * json = strstr( (const char*)buf, "\r\n\r\n" ) + 4;

            if ( !json )
                break;

            if ( !ParseMatchResponse( json, m_matchResponse ) )
            {
                m_status = MATCHER_FAILED;
                goto cleanup;
            }

            m_status = MATCHER_READY;

            goto cleanup;
        }
        while( 1 );

        m_status = MATCHER_FAILED;

    cleanup:

        mbedtls_ssl_close_notify( &m_internal->ssl );
    }

    MatcherStatus Matcher::GetStatus()
    {
        return m_status;
    }

    void Matcher::GetMatchResponse( MatchResponse & matchResponse )
    {
        matchResponse = ( m_status == MATCHER_READY ) ? m_matchResponse : MatchResponse();
    }

    static bool exists_and_is_string( Document & doc, const char * key )
    {
        return doc.HasMember( key ) && doc[key].IsString();
    }

    static bool exists_and_is_array( Document & doc, const char * key )
    {
        return doc.HasMember( key ) && doc[key].IsArray();
    }

    bool Matcher::ParseMatchResponse( const char * json, MatchResponse & matchResponse )
    {
        Document doc;
        doc.Parse( json );
        if ( doc.HasParseError() )
            return false;

        if ( !exists_and_is_string( doc, "connectTokenData" ) )
            return false;

        if ( !exists_and_is_string( doc, "connectTokenNonce" ) )
            return false;

        if ( !exists_and_is_array( doc, "serverAddresses" ) )
            return false;

        if ( !exists_and_is_string( doc, "clientToServerKey" ) )
            return false;

        if ( !exists_and_is_string( doc, "serverToClientKey" ) )
            return false;

        const char * encryptedConnectTokenBase64 = doc["connectTokenData"].GetString();

        int encryptedLength = base64_decode_data( encryptedConnectTokenBase64, matchResponse.connectTokenData, ConnectTokenBytes );

        if ( encryptedLength != ConnectTokenBytes )
            return false;

        uint64_t connectTokenNonce = atoll( doc["connectTokenNonce"].GetString() );

        memcpy( &matchResponse.connectTokenNonce, &connectTokenNonce, 8 );

        matchResponse.numServerAddresses = 0;

        const Value & serverAddresses = doc["serverAddresses"];

        if ( !serverAddresses.IsArray() )
            return false;

        for ( SizeType i = 0; i < serverAddresses.Size(); ++i )
        {
            if ( i >= MaxServersPerConnectToken )
                return false;

            if ( !serverAddresses[i].IsString() )
                return false;

            char serverAddress[MaxAddressLength];

            base64_decode_string( serverAddresses[i].GetString(), serverAddress, sizeof( serverAddress ) );

            matchResponse.serverAddresses[i] = Address( serverAddress );

            if ( !matchResponse.serverAddresses[i].IsValid() )
                return false;

            matchResponse.numServerAddresses++;
        }

        const char * clientToServerKeyBase64 = doc["clientToServerKey"].GetString();

        const char * serverToClientKeyBase64 = doc["serverToClientKey"].GetString();

        if ( base64_decode_data( clientToServerKeyBase64, matchResponse.clientToServerKey, KeyBytes ) != KeyBytes )
            return false;

        if ( base64_decode_data( serverToClientKeyBase64, matchResponse.serverToClientKey, KeyBytes ) != KeyBytes )
            return false;

        return true;
    }
}
<commit_msg>fix return instead of goto cleanup bug in matcher<commit_after>/*
    Yojimbo Client/Server Network Library.

    Copyright © 2016, The Network Protocol Company, Inc.

    Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

        1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

        2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
           in the documentation and/or other materials provided with the distribution.

        3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived
           from this software without specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
    USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "yojimbo_matcher.h"

#include <mbedtls/config.h>
#include <mbedtls/platform.h>
#include <mbedtls/net.h>
#include <mbedtls/debug.h>
#include <mbedtls/ssl.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/error.h>
#include <mbedtls/certs.h>

#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"

#include "sodium.h"

using namespace rapidjson;

#define SERVER_PORT "8080"
#define SERVER_NAME "localhost"

namespace yojimbo
{
    struct MatcherInternal
    {
        mbedtls_net_context server_fd;
        mbedtls_entropy_context entropy;
        mbedtls_ctr_drbg_context ctr_drbg;
        mbedtls_ssl_context ssl;
        mbedtls_ssl_config conf;
        mbedtls_x509_crt cacert;
    };

    Matcher::Matcher( Allocator & allocator )
    {
        m_allocator = &allocator;
        m_initialized = false;
        m_status = MATCHER_IDLE;
        m_internal = YOJIMBO_NEW( allocator, MatcherInternal );
    }

    Matcher::~Matcher()
    {
        mbedtls_net_free( &m_internal->server_fd );
        mbedtls_x509_crt_free( &m_internal->cacert );
        mbedtls_ssl_free( &m_internal->ssl );
        mbedtls_ssl_config_free( &m_internal->conf );
        mbedtls_ctr_drbg_free( &m_internal->ctr_drbg );
        mbedtls_entropy_free( &m_internal->entropy );

        YOJIMBO_DELETE( *m_allocator, MatcherInternal, m_internal );
    }

    bool Matcher::Initialize()
    {
        const char * pers = "yojimbo_client";

        mbedtls_net_init( &m_internal->server_fd );
        mbedtls_ssl_init( &m_internal->ssl );
        mbedtls_ssl_config_init( &m_internal->conf );
        mbedtls_x509_crt_init( &m_internal->cacert );
        mbedtls_ctr_drbg_init( &m_internal->ctr_drbg );
        mbedtls_entropy_init( &m_internal->entropy );

        int result;

        if ( ( result = mbedtls_ctr_drbg_seed( &m_internal->ctr_drbg, mbedtls_entropy_func, &m_internal->entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 )
        {
            return false;
        }

        if ( mbedtls_x509_crt_parse( &m_internal->cacert, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ) < 0 )
        {
            return false;
        }

        m_initialized = true;

        return true;
    }

    void Matcher::RequestMatch( uint32_t protocolId, uint64_t clientId )
    {
        assert( m_initialized );

        int ret, len;
        uint32_t flags;
        char buf[4*1024];
        char request[1024];

        if ( ( ret = mbedtls_net_connect( &m_internal->server_fd, SERVER_NAME, SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 )
        {
            m_status = MATCHER_FAILED;
            goto cleanup;
        }

        if ( ( ret = mbedtls_ssl_config_defaults( &m_internal->conf,
                        MBEDTLS_SSL_IS_CLIENT,
                        MBEDTLS_SSL_TRANSPORT_STREAM,
                        MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
        {
            m_status = MATCHER_FAILED;
            goto cleanup;
        }

        mbedtls_ssl_conf_authmode( &m_internal->conf, MBEDTLS_SSL_VERIFY_OPTIONAL );
        mbedtls_ssl_conf_ca_chain( &m_internal->conf, &m_internal->cacert, NULL );
        mbedtls_ssl_conf_rng( &m_internal->conf, mbedtls_ctr_drbg_random, &m_internal->ctr_drbg );

        if( ( ret = mbedtls_ssl_setup( &m_internal->ssl, &m_internal->conf ) ) != 0 )
        {
            m_status = MATCHER_FAILED;
            goto cleanup;
        }

        if ( ( ret = mbedtls_ssl_set_hostname( &m_internal->ssl, "yojimbo" ) ) != 0 )
        {
            m_status = MATCHER_FAILED;
            goto cleanup;
        }

        mbedtls_ssl_set_bio( &m_internal->ssl, &m_internal->server_fd, mbedtls_net_send, mbedtls_net_recv, NULL );

        while ( ( ret = mbedtls_ssl_handshake( &m_internal->ssl ) ) != 0 )
        {
            if ( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
            {
                m_status = MATCHER_FAILED;
                goto cleanup;
            }
        }

        if ( ( flags = mbedtls_ssl_get_verify_result( &m_internal->ssl ) ) != 0 )
        {
            // could not verify certificate (eg. it is self-signed)

            // IMPORTANT: this should be locked down #if YOJIMBO_SECURE
        }

        sprintf( request, "GET /match/%d/%" PRIu64 " HTTP/1.0\r\n\r\n", protocolId, clientId );

        while ( ( ret = mbedtls_ssl_write( &m_internal->ssl, (uint8_t*) request, strlen( request ) ) ) <= 0 )
        {
            if ( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
            {
                m_status = MATCHER_FAILED;
                goto cleanup;
            }
        }

        do
        {
            len = sizeof( buf ) - 1;
            memset( buf, 0, sizeof( buf ) );
            ret = mbedtls_ssl_read( &m_internal->ssl, (uint8_t*) buf, len );

            if ( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE )
                continue;

            if ( ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY )
                break;

            if ( ret <= 0 )
                break;

            const char * json = strstr( (const char*)buf, "\r\n\r\n" ) + 4;

            if ( !json )
                break;

            if ( !ParseMatchResponse( json, m_matchResponse ) )
            {
                m_status = MATCHER_FAILED;
                goto cleanup;
            }

            m_status = MATCHER_READY;

            goto cleanup;
        }
        while( 1 );

        m_status = MATCHER_FAILED;

    cleanup:

        mbedtls_ssl_close_notify( &m_internal->ssl );
    }

    MatcherStatus Matcher::GetStatus()
    {
        return m_status;
    }

    void Matcher::GetMatchResponse( MatchResponse & matchResponse )
    {
        matchResponse = ( m_status == MATCHER_READY ) ? m_matchResponse : MatchResponse();
    }

    static bool exists_and_is_string( Document & doc, const char * key )
    {
        return doc.HasMember( key ) && doc[key].IsString();
    }

    static bool exists_and_is_array( Document & doc, const char * key )
    {
        return doc.HasMember( key ) && doc[key].IsArray();
    }

    bool Matcher::ParseMatchResponse( const char * json, MatchResponse & matchResponse )
    {
        Document doc;
        doc.Parse( json );
        if ( doc.HasParseError() )
            return false;

        if ( !exists_and_is_string( doc, "connectTokenData" ) )
            return false;

        if ( !exists_and_is_string( doc, "connectTokenNonce" ) )
            return false;

        if ( !exists_and_is_array( doc, "serverAddresses" ) )
            return false;

        if ( !exists_and_is_string( doc, "clientToServerKey" ) )
            return false;

        if ( !exists_and_is_string( doc, "serverToClientKey" ) )
            return false;

        const char * encryptedConnectTokenBase64 = doc["connectTokenData"].GetString();

        int encryptedLength = base64_decode_data( encryptedConnectTokenBase64, matchResponse.connectTokenData, ConnectTokenBytes );

        if ( encryptedLength != ConnectTokenBytes )
            return false;

        uint64_t connectTokenNonce = atoll( doc["connectTokenNonce"].GetString() );

        memcpy( &matchResponse.connectTokenNonce, &connectTokenNonce, 8 );

        matchResponse.numServerAddresses = 0;

        const Value & serverAddresses = doc["serverAddresses"];

        if ( !serverAddresses.IsArray() )
            return false;

        for ( SizeType i = 0; i < serverAddresses.Size(); ++i )
        {
            if ( i >= MaxServersPerConnectToken )
                return false;

            if ( !serverAddresses[i].IsString() )
                return false;

            char serverAddress[MaxAddressLength];

            base64_decode_string( serverAddresses[i].GetString(), serverAddress, sizeof( serverAddress ) );

            matchResponse.serverAddresses[i] = Address( serverAddress );

            if ( !matchResponse.serverAddresses[i].IsValid() )
                return false;

            matchResponse.numServerAddresses++;
        }

        const char * clientToServerKeyBase64 = doc["clientToServerKey"].GetString();

        const char * serverToClientKeyBase64 = doc["serverToClientKey"].GetString();

        if ( base64_decode_data( clientToServerKeyBase64, matchResponse.clientToServerKey, KeyBytes ) != KeyBytes )
            return false;

        if ( base64_decode_data( serverToClientKeyBase64, matchResponse.serverToClientKey, KeyBytes ) != KeyBytes )
            return false;

        return true;
    }
}
<|endoftext|>


<commit_before>#include "commit.h"

Persistent<FunctionTemplate> Commit::constructor_template;

void Commit::Init(Handle<Object> target) {
	HandleScope scope;

	Local<FunctionTemplate> t = FunctionTemplate::New(New);
	constructor_template = Persistent<FunctionTemplate>::New(t);
	constructor_template->SetClassName(String::New("Commit"));
	t->InstanceTemplate()->SetInternalFieldCount(1);

	NODE_SET_PROTOTYPE_METHOD(t, "getTree", GetTree);
	NODE_SET_PROTOTYPE_METHOD(t, "getParent", GetParent);
	//t->PrototypeTemplate()->SetAccessor(COMMIT_TREE_SYMBOL, TreeGetter);
}

Handle<Value> Commit::New(const Arguments& args) {
	HandleScope scope;

	REQ_ARGS(1);
	REQ_EXT_ARG(0, theCommit);
	//REQ_EXT_ARG(1, theRepo);

	Commit *commit = new Commit();
	commit->commit_ = (git_commit*)theCommit->Value();
	//commit->repo_ = (Repository*)theRepo->Value();

	// Setup some basic info about this commit.
	const char* oidStr = git_oid_allocfmt(git_commit_id(commit->commit_));
	args.This()->Set(String::New("id"), String::New(oidStr), ReadOnly);

	const char* message = git_commit_message(commit->commit_);
	args.This()->Set(String::New("message"), String::New(message));

	const char* shortMessage = git_commit_message_short(commit->commit_);
	args.This()->Set(String::New("shortMessage"), String::New(shortMessage), ReadOnly);

	time_t time = git_commit_time(commit->commit_);
	args.This()->Set(String::New("time"), Date::New(static_cast<double>(time)*1000));

	const git_signature *author;
	author = git_commit_author(commit->commit_);
	CREATE_PERSON_OBJ(authorObj, author);
	args.This()->Set(String::New("author"), authorObj);

	const git_signature *committer;
	committer = git_commit_committer(commit->commit_);
	CREATE_PERSON_OBJ(committerObj, committer);
	args.This()->Set(String::New("committer"), committerObj);

	commit->parentCount_ = git_commit_parentcount(commit->commit_);

/*	// Setup the parents.
	Handle<ObjectTemplate> parentObjectTemplate = ObjectTemplate::New();
	parentObjectTemplate->SetInternalFieldCount(1);
	parentObjectTemplate->SetIndexedPropertyHandler(IndexedParentGetter);

	Handle<Object> parentsObject = parentObjectTemplate->NewInstance();
	parentsObject->SetInternalField(0, args.This());
	parentsObject->Set(String::New("length"), Integer::New(commit->parentCount_));

	args.This()->Set(String::New("parents"), parentsObject, ReadOnly);*/

	args.This()->Set(String::New("parentCount"), Integer::New(commit->parentCount_), ReadOnly);

	commit->Wrap(args.This());
	return args.This();
}

Handle<Value> Commit::GetTree(const Arguments& args) {
	HandleScope scope;

	Commit *commit = ObjectWrap::Unwrap<Commit>(args.This());

	const git_tree *tree = git_commit_tree(commit->commit_);

	Tree *treeObject = commit->repository_->wrapTree(const_cast<git_tree*>(tree));
	return treeObject->handle_;
}

Handle<Value> Commit::GetParent(const Arguments& args) {
	HandleScope scope;

	Commit *commit = ObjectWrap::Unwrap<Commit>(args.This());

	REQ_ARGS(1);
	REQ_INT_ARG(0, index);

	if(index >= commit->parentCount_) {
		return ThrowException(Exception::Error(String::New("Parent commit index is out of bounds.")));
	}

	git_commit *parent = git_commit_parent(commit->commit_, index);
	Commit *parentObject = commit->repository_->wrapCommit(parent);
	return parentObject->handle_;
}

Commit::~Commit() {
	// TODO: don't think we ever need to free commits as they're handled by the repo, even newly created ones
	// (I think), probably need to look into this.
}
<commit_msg>cleanup<commit_after>#include "commit.h"

Persistent<FunctionTemplate> Commit::constructor_template;

void Commit::Init(Handle<Object> target) {
	HandleScope scope;

	Local<FunctionTemplate> t = FunctionTemplate::New(New);
	constructor_template = Persistent<FunctionTemplate>::New(t);
	constructor_template->SetClassName(String::New("Commit"));
	t->InstanceTemplate()->SetInternalFieldCount(1);

	NODE_SET_PROTOTYPE_METHOD(t, "getTree", GetTree);
	NODE_SET_PROTOTYPE_METHOD(t, "getParent", GetParent);
	//t->PrototypeTemplate()->SetAccessor(COMMIT_TREE_SYMBOL, TreeGetter);
}

Handle<Value> Commit::New(const Arguments& args) {
	HandleScope scope;

	REQ_ARGS(1);
	REQ_EXT_ARG(0, theCommit);
	//REQ_EXT_ARG(1, theRepo);

	Commit *commit = new Commit();
	commit->commit_ = (git_commit*)theCommit->Value();
	//commit->repo_ = (Repository*)theRepo->Value();

	// Setup some basic info about this commit.
	const char* oidStr = git_oid_allocfmt(git_commit_id(commit->commit_));
	args.This()->Set(String::New("id"), String::New(oidStr), ReadOnly);

	const char* message = git_commit_message(commit->commit_);
	args.This()->Set(String::New("message"), String::New(message));

	const char* shortMessage = git_commit_message_short(commit->commit_);
	args.This()->Set(String::New("shortMessage"), String::New(shortMessage), ReadOnly);

	time_t time = git_commit_time(commit->commit_);
	args.This()->Set(String::New("time"), Date::New(static_cast<double>(time)*1000));

	const git_signature *author;
	author = git_commit_author(commit->commit_);
	CREATE_PERSON_OBJ(authorObj, author);
	args.This()->Set(String::New("author"), authorObj);

	const git_signature *committer;
	committer = git_commit_committer(commit->commit_);
	CREATE_PERSON_OBJ(committerObj, committer);
	args.This()->Set(String::New("committer"), committerObj);

	commit->parentCount_ = git_commit_parentcount(commit->commit_);

	args.This()->Set(String::New("parentCount"), Integer::New(commit->parentCount_), ReadOnly);

	commit->Wrap(args.This());
	return args.This();
}

Handle<Value> Commit::GetTree(const Arguments& args) {
	HandleScope scope;

	Commit *commit = ObjectWrap::Unwrap<Commit>(args.This());

	const git_tree *tree = git_commit_tree(commit->commit_);

	Tree *treeObject = commit->repository_->wrapTree(const_cast<git_tree*>(tree));
	return treeObject->handle_;
}

Handle<Value> Commit::GetParent(const Arguments& args) {
	HandleScope scope;

	Commit *commit = ObjectWrap::Unwrap<Commit>(args.This());

	REQ_ARGS(1);
	REQ_INT_ARG(0, index);

	if(index >= commit->parentCount_) {
		return ThrowException(Exception::Error(String::New("Parent commit index is out of bounds.")));
	}

	git_commit *parent = git_commit_parent(commit->commit_, index);
	Commit *parentObject = commit->repository_->wrapCommit(parent);
	return parentObject->handle_;
}

Commit::~Commit() {
	// TODO: don't think we ever need to free commits as they're handled by the repo, even newly created ones
	// (I think), probably need to look into this.
}
<|endoftext|>


<commit_before>/*
* Client Key Exchange Message
* (C) 2004-2010 Jack Lloyd
*
* Released under the terms of the Botan license
*/

#include <botan/internal/tls_messages.h>
#include <botan/internal/tls_reader.h>
#include <botan/internal/tls_extensions.h>
#include <botan/pubkey.h>
#include <botan/dh.h>
#include <botan/ecdh.h>
#include <botan/rsa.h>
#include <botan/rng.h>
#include <botan/loadstor.h>
#include <memory>

namespace Botan {

namespace TLS {

namespace {

SecureVector<byte> strip_leading_zeros(const MemoryRegion<byte>& input)
   {
   size_t leading_zeros = 0;

   for(size_t i = 0; i != input.size(); ++i)
      {
      if(input[i] != 0)
         break;
      ++leading_zeros;
      }

   SecureVector<byte> output(&input[leading_zeros],
                             input.size() - leading_zeros);
   return output;
   }

}

/*
* Create a new Client Key Exchange message
*/
Client_Key_Exchange::Client_Key_Exchange(Record_Writer& writer,
                                         Handshake_State* state,
                                         const std::vector<X509_Certificate>& peer_certs,
                                         RandomNumberGenerator& rng)
   {
   if(state->server_kex)
      {
      TLS_Data_Reader reader(state->server_kex->params());

      if(state->suite.kex_algo() == "DH")
         {
         BigInt p = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
         BigInt g = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
         BigInt Y = BigInt::decode(reader.get_range<byte>(2, 1, 65535));

         if(reader.remaining_bytes())
            throw Decoding_Error("Bad params size for DH key exchange");

         DL_Group group(p, g);

         if(!group.verify_group(rng, true))
            throw Internal_Error("DH group failed validation, possible attack");

         DH_PublicKey counterparty_key(group, Y);

         // FIXME Check that public key is residue?

         DH_PrivateKey priv_key(rng, group);

         PK_Key_Agreement ka(priv_key, "Raw");

         pre_master = strip_leading_zeros(
            ka.derive_key(0, counterparty_key.public_value()).bits_of());

         append_tls_length_value(key_material, priv_key.public_value(), 2);
         }
      else if(state->suite.kex_algo() == "ECDH")
         {
         const byte curve_type = reader.get_byte();

         if(curve_type != 3)
            throw Decoding_Error("Server sent non-named ECC curve");

         const u16bit curve_id = reader.get_u16bit();

         const std::string name = Supported_Elliptic_Curves::curve_id_to_name(curve_id);

         if(name == "")
            throw Decoding_Error("Server sent unknown named curve " + to_string(curve_id));

         EC_Group group(name);

         MemoryVector<byte> ecdh_key = reader.get_range<byte>(1, 1, 255);

         ECDH_PublicKey counterparty_key(group, OS2ECP(ecdh_key, group.get_curve()));

         ECDH_PrivateKey priv_key(rng, group);

         PK_Key_Agreement ka(priv_key, "Raw");

         pre_master = strip_leading_zeros(
            ka.derive_key(0, counterparty_key.public_value()).bits_of());

         append_tls_length_value(key_material, priv_key.public_value(), 1);
         }
      else
         throw Internal_Error("Server key exchange type " + state->suite.kex_algo() +
                              " not known");
      }
   else
      {
      // No server key exchange msg better mean a RSA key in the cert

      std::auto_ptr<Public_Key> pub_key(peer_certs[0].subject_public_key());

      if(peer_certs.empty())
         throw Internal_Error("No certificate and no server key exchange");

      if(const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(pub_key.get()))
         {
         const Protocol_Version pref_version = state->client_hello->version();

         pre_master = rng.random_vec(48);
         pre_master[0] = pref_version.major_version();
         pre_master[1] = pref_version.minor_version();

         PK_Encryptor_EME encryptor(*rsa_pub, "PKCS1v15");

         MemoryVector<byte> encrypted_key = encryptor.encrypt(pre_master, rng);

         if(state->version == Protocol_Version::SSL_V3)
            key_material = encrypted_key; // no length field
         else
            append_tls_length_value(key_material, encrypted_key, 2);
         }
      else
         throw TLS_Exception(HANDSHAKE_FAILURE,
                             "Expected a RSA key in server cert but got " +
                             pub_key->algo_name());
      }

   send(writer, state->hash);
   }

/*
* Read a Client Key Exchange message
*/
Client_Key_Exchange::Client_Key_Exchange(const MemoryRegion<byte>& contents,
                                         const Ciphersuite& suite,
                                         Protocol_Version using_version)
   {
   if(suite.kex_algo() == "" && using_version == Protocol_Version::SSL_V3)
      key_material = contents;
   else
      {
      TLS_Data_Reader reader(contents);

      if(suite.kex_algo() == "" || suite.kex_algo() == "DH")
         key_material = reader.get_range<byte>(2, 0, 65535);
      else if(suite.kex_algo() == "ECDH")
         key_material = reader.get_range<byte>(1, 1, 255);
      else
         throw Internal_Error("Unknown client key exch type " + suite.kex_algo());
      }
   }

/*
* Return the pre_master_secret
*/
SecureVector<byte>
Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng,
                                       const Private_Key* priv_key,
                                       Protocol_Version client_version)
   {
   if(const RSA_PrivateKey* rsa = dynamic_cast<const RSA_PrivateKey*>(priv_key))
      {
      PK_Decryptor_EME decryptor(*rsa, "PKCS1v15");

      try {
         pre_master = decryptor.decrypt(key_material);

         if(pre_master.size() != 48 ||
            client_version.major_version() != pre_master[0] ||
            client_version.minor_version() != pre_master[1])
            {
            throw Decoding_Error("Client_Key_Exchange: Secret corrupted");
            }
      }
      catch(...)
         {
         pre_master = rng.random_vec(48);
         pre_master[0] = client_version.major_version();
         pre_master[1] = client_version.minor_version();
         }

      return pre_master;
      }

   // DH or ECDH
   if(const PK_Key_Agreement_Key* dh = dynamic_cast<const PK_Key_Agreement_Key*>(priv_key))
      {
      try {
         PK_Key_Agreement ka(*dh, "Raw");

         pre_master = strip_leading_zeros(ka.derive_key(0, key_material).bits_of());
      }
      catch(...)
         {
         /*
         * Something failed in the DH computation. To avoid possible
         * timing attacks, randomize the pre-master output and carry
         * on, allowing the protocol to fail later in the finished
         * checks.
         */
         pre_master = rng.random_vec(dh->public_value().size());
         }

      return pre_master;
      }

   throw Invalid_Argument("Client_Key_Exchange: Unknown key type " + priv_key->algo_name());
   }

}

}
<commit_msg>For ECDH you don't strip leading zeros. Bikeshedding: 1 Consistency: 0<commit_after>/*
* Client Key Exchange Message
* (C) 2004-2010 Jack Lloyd
*
* Released under the terms of the Botan license
*/

#include <botan/internal/tls_messages.h>
#include <botan/internal/tls_reader.h>
#include <botan/internal/tls_extensions.h>
#include <botan/pubkey.h>
#include <botan/dh.h>
#include <botan/ecdh.h>
#include <botan/rsa.h>
#include <botan/rng.h>
#include <botan/loadstor.h>
#include <memory>

namespace Botan {

namespace TLS {

namespace {

SecureVector<byte> strip_leading_zeros(const MemoryRegion<byte>& input)
   {
   size_t leading_zeros = 0;

   for(size_t i = 0; i != input.size(); ++i)
      {
      if(input[i] != 0)
         break;
      ++leading_zeros;
      }

   SecureVector<byte> output(&input[leading_zeros],
                             input.size() - leading_zeros);
   return output;
   }

}

/*
* Create a new Client Key Exchange message
*/
Client_Key_Exchange::Client_Key_Exchange(Record_Writer& writer,
                                         Handshake_State* state,
                                         const std::vector<X509_Certificate>& peer_certs,
                                         RandomNumberGenerator& rng)
   {
   if(state->server_kex)
      {
      TLS_Data_Reader reader(state->server_kex->params());

      if(state->suite.kex_algo() == "DH")
         {
         BigInt p = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
         BigInt g = BigInt::decode(reader.get_range<byte>(2, 1, 65535));
         BigInt Y = BigInt::decode(reader.get_range<byte>(2, 1, 65535));

         if(reader.remaining_bytes())
            throw Decoding_Error("Bad params size for DH key exchange");

         DL_Group group(p, g);

         if(!group.verify_group(rng, true))
            throw Internal_Error("DH group failed validation, possible attack");

         DH_PublicKey counterparty_key(group, Y);

         // FIXME Check that public key is residue?

         DH_PrivateKey priv_key(rng, group);

         PK_Key_Agreement ka(priv_key, "Raw");

         pre_master = strip_leading_zeros(
            ka.derive_key(0, counterparty_key.public_value()).bits_of());

         append_tls_length_value(key_material, priv_key.public_value(), 2);
         }
      else if(state->suite.kex_algo() == "ECDH")
         {
         const byte curve_type = reader.get_byte();

         if(curve_type != 3)
            throw Decoding_Error("Server sent non-named ECC curve");

         const u16bit curve_id = reader.get_u16bit();

         const std::string name = Supported_Elliptic_Curves::curve_id_to_name(curve_id);

         if(name == "")
            throw Decoding_Error("Server sent unknown named curve " + to_string(curve_id));

         EC_Group group(name);

         MemoryVector<byte> ecdh_key = reader.get_range<byte>(1, 1, 255);

         ECDH_PublicKey counterparty_key(group, OS2ECP(ecdh_key, group.get_curve()));

         ECDH_PrivateKey priv_key(rng, group);

         PK_Key_Agreement ka(priv_key, "Raw");

         pre_master = ka.derive_key(0, counterparty_key.public_value()).bits_of();

         append_tls_length_value(key_material, priv_key.public_value(), 1);
         }
      else
         throw Internal_Error("Server key exchange type " + state->suite.kex_algo() +
                              " not known");
      }
   else
      {
      // No server key exchange msg better mean a RSA key in the cert

      std::auto_ptr<Public_Key> pub_key(peer_certs[0].subject_public_key());

      if(peer_certs.empty())
         throw Internal_Error("No certificate and no server key exchange");

      if(const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(pub_key.get()))
         {
         const Protocol_Version pref_version = state->client_hello->version();

         pre_master = rng.random_vec(48);
         pre_master[0] = pref_version.major_version();
         pre_master[1] = pref_version.minor_version();

         PK_Encryptor_EME encryptor(*rsa_pub, "PKCS1v15");

         MemoryVector<byte> encrypted_key = encryptor.encrypt(pre_master, rng);

         if(state->version == Protocol_Version::SSL_V3)
            key_material = encrypted_key; // no length field
         else
            append_tls_length_value(key_material, encrypted_key, 2);
         }
      else
         throw TLS_Exception(HANDSHAKE_FAILURE,
                             "Expected a RSA key in server cert but got " +
                             pub_key->algo_name());
      }

   send(writer, state->hash);
   }

/*
* Read a Client Key Exchange message
*/
Client_Key_Exchange::Client_Key_Exchange(const MemoryRegion<byte>& contents,
                                         const Ciphersuite& suite,
                                         Protocol_Version using_version)
   {
   if(suite.kex_algo() == "" && using_version == Protocol_Version::SSL_V3)
      key_material = contents;
   else
      {
      TLS_Data_Reader reader(contents);

      if(suite.kex_algo() == "" || suite.kex_algo() == "DH")
         key_material = reader.get_range<byte>(2, 0, 65535);
      else if(suite.kex_algo() == "ECDH")
         key_material = reader.get_range<byte>(1, 1, 255);
      else
         throw Internal_Error("Unknown client key exch type " + suite.kex_algo());
      }
   }

/*
* Return the pre_master_secret
*/
SecureVector<byte>
Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng,
                                       const Private_Key* priv_key,
                                       Protocol_Version client_version)
   {
   if(const RSA_PrivateKey* rsa = dynamic_cast<const RSA_PrivateKey*>(priv_key))
      {
      PK_Decryptor_EME decryptor(*rsa, "PKCS1v15");

      try {
         pre_master = decryptor.decrypt(key_material);

         if(pre_master.size() != 48 ||
            client_version.major_version() != pre_master[0] ||
            client_version.minor_version() != pre_master[1])
            {
            throw Decoding_Error("Client_Key_Exchange: Secret corrupted");
            }
      }
      catch(...)
         {
         pre_master = rng.random_vec(48);
         pre_master[0] = client_version.major_version();
         pre_master[1] = client_version.minor_version();
         }

      return pre_master;
      }

   // DH or ECDH
   if(const PK_Key_Agreement_Key* dh = dynamic_cast<const PK_Key_Agreement_Key*>(priv_key))
      {
      try {
         PK_Key_Agreement ka(*dh, "Raw");

         if(dh->algo_name() == "DH")
            pre_master = strip_leading_zeros(ka.derive_key(0, key_material).bits_of());
         else
            pre_master = ka.derive_key(0, key_material).bits_of();
      }
      catch(...)
         {
         /*
         * Something failed in the DH computation. To avoid possible
         * timing attacks, randomize the pre-master output and carry
         * on, allowing the protocol to fail later in the finished
         * checks.
         */
         pre_master = rng.random_vec(dh->public_value().size());
         }

      return pre_master;
      }

   throw Invalid_Argument("Client_Key_Exchange: Unknown key type " + priv_key->algo_name());
   }

}

}
<|endoftext|>


<commit_before>/*             ___
              / | |_   _ ___ _ __ __  __ _____
             / /| | | / /   |  __/ / / /_____/
            / / | | |/ / /| | | / /_/ /__\ \
           /_/  |_|___/_/ |_|_| \____/_____/

Copyright (C) 2019 Jack Steilberg <jsteil123@gmail.com>

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Affero General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

A copy of the GNU Affero General Public License should accompany
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "MainLoop.h"

/*MainLoop::MainLoop(Player &player, b2World &world, DebugOverlay &dbg_overlay,
                   Console &console_overlay)
    : player_(player), world_(world), dbg_overlay_(dbg_overlay),
      console_overlay_(console_overlay) {

  console_on_ = false;
  }*/
MainLoop::MainLoop(Game *game) : game_(game) { console_on_ = false; }

void MainLoop::Update(const sf::Time &deltaTime, sf::Window &window) {
  // TODO: Maybe handling key events should be outside update?
  HandleKeyEvents(window);

  game_->world_.Step(deltaTime.asSeconds(), consts::kVelocityIterations,
                     consts::kPositionIterations);
  game_->player_.Update(deltaTime);

  if (game_->dbg_overlay_.IsActive()) {
    game_->dbg_overlay_.Update();
  }
}

void MainLoop::Draw(sf::RenderWindow &window) {
  window.draw(game_->player_.GetSprite());

  if (game_->dbg_overlay_.IsActive()) {
    window.draw(game_->dbg_overlay_);
  }
}

bool IsKeyPressed(sf::Keyboard::Key key) {
  return sf::Keyboard::isKeyPressed(key);
}

void MainLoop::HandleKeyEvents(sf::Window &window) {
  if (IsKeyPressed(sf::Keyboard::Up) or IsKeyPressed(sf::Keyboard::W)) {
    game_->player_.ApplyForce(b2Vec2(0, -15));
  }

  if (IsKeyPressed(sf::Keyboard::Down) or IsKeyPressed(sf::Keyboard::S)) {
    game_->player_.ApplyForce(b2Vec2(0, 15));
  }

  if (IsKeyPressed(sf::Keyboard::Left) or IsKeyPressed(sf::Keyboard::A)) {
    game_->player_.ApplyForce(b2Vec2(-15, 0));
  }

  if (IsKeyPressed(sf::Keyboard::Right) or IsKeyPressed(sf::Keyboard::D)) {
    game_->player_.ApplyForce(b2Vec2(15, 0));
  }

  if (IsKeyPressed(sf::Keyboard::R)) {
    game_->player_.SetRot(game_->player_.GetRot() + 1);
  }

  sf::Event event;

  while (window.pollEvent(event)) {
    if (event.type == sf::Event::Closed) {
      window.close();
    } else if (event.type == sf::Event::KeyPressed) {
      switch (event.key.code) {
      case sf::Keyboard::Escape:
        window.close();
        break;

      case sf::Keyboard::F3:
        game_->dbg_overlay_.Toggle();

        // Ya know, sometimes people rail on ternary if statements.
        // Everything in moderation.
        Logger::Log(string("Debug menu turned ") +
                        (game_->dbg_overlay_.IsActive() ? "on" : "off"),
                    INFO);
        break;
      case sf::Keyboard::BackSlash:
        game_->window_.setKeyRepeatEnabled(true);
        game_->AddState(game_->console_loop_);
        break;
      case sf::Keyboard::T:
        game_->player_.SetCurrentTexture(
            game_->player_.GetCurrentTexture() == "norm" ? "hurt" : "norm");
        Logger::Log("Set player texture to " +
                        game_->player_.GetCurrentTexture(),
                    INFO);
        break;

      default:
        break;
      }
    }
  }
}

const string MainLoop::ToString() const { return "Main Loop"; }

MainLoop::~MainLoop() {
  // dtor
}
<commit_msg>Added resizing for window (buggy)<commit_after>/*             ___
              / | |_   _ ___ _ __ __  __ _____
             / /| | | / /   |  __/ / / /_____/
            / / | | |/ / /| | | / /_/ /__\ \
           /_/  |_|___/_/ |_|_| \____/_____/

Copyright (C) 2019 Jack Steilberg <jsteil123@gmail.com>

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Affero General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

A copy of the GNU Affero General Public License should accompany
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "MainLoop.h"

/*MainLoop::MainLoop(Player &player, b2World &world, DebugOverlay &dbg_overlay,
                   Console &console_overlay)
    : player_(player), world_(world), dbg_overlay_(dbg_overlay),
      console_overlay_(console_overlay) {

  console_on_ = false;
  }*/
MainLoop::MainLoop(Game *game) : game_(game) { console_on_ = false; }

void MainLoop::Update(const sf::Time &deltaTime, sf::Window &window) {
  // TODO: Maybe handling key events should be outside update?
  HandleKeyEvents(window);

  game_->world_.Step(deltaTime.asSeconds(), consts::kVelocityIterations,
                     consts::kPositionIterations);
  game_->player_.Update(deltaTime);

  if (game_->dbg_overlay_.IsActive()) {
    game_->dbg_overlay_.Update();
  }
}

void MainLoop::Draw(sf::RenderWindow &window) {
  window.draw(game_->player_.GetSprite());

  if (game_->dbg_overlay_.IsActive()) {
    window.draw(game_->dbg_overlay_);
  }
}

bool IsKeyPressed(sf::Keyboard::Key key) {
  return sf::Keyboard::isKeyPressed(key);
}

void MainLoop::HandleKeyEvents(sf::Window &window) {
  if (IsKeyPressed(sf::Keyboard::Up) or IsKeyPressed(sf::Keyboard::W)) {
    game_->player_.ApplyForce(b2Vec2(0, -15));
  }

  if (IsKeyPressed(sf::Keyboard::Down) or IsKeyPressed(sf::Keyboard::S)) {
    game_->player_.ApplyForce(b2Vec2(0, 15));
  }

  if (IsKeyPressed(sf::Keyboard::Left) or IsKeyPressed(sf::Keyboard::A)) {
    game_->player_.ApplyForce(b2Vec2(-15, 0));
  }

  if (IsKeyPressed(sf::Keyboard::Right) or IsKeyPressed(sf::Keyboard::D)) {
    game_->player_.ApplyForce(b2Vec2(15, 0));
  }

  if (IsKeyPressed(sf::Keyboard::R)) {
    game_->player_.SetRot(game_->player_.GetRot() + 1);
  }

  sf::Event event;

  while (window.pollEvent(event)) {
    // catch the resize events
    if (event.type == sf::Event::Resized) {
      // update the view to the new size of the window
      sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height);
      Logger::Log("Resize event", INFO);
      game_->window_.setView(sf::View(visibleArea));
    } else if (event.type == sf::Event::Closed) {
      window.close();
    } else if (event.type == sf::Event::KeyPressed) {
      switch (event.key.code) {
      case sf::Keyboard::Escape:
        window.close();
        break;

      case sf::Keyboard::F3:
        game_->dbg_overlay_.Toggle();

        // Ya know, sometimes people rail on ternary if statements.
        // Everything in moderation.
        Logger::Log(string("Debug menu turned ") +
                        (game_->dbg_overlay_.IsActive() ? "on" : "off"),
                    INFO);
        break;
      case sf::Keyboard::BackSlash:
        game_->window_.setKeyRepeatEnabled(true);
        game_->AddState(game_->console_loop_);
        break;
      case sf::Keyboard::T:
        game_->player_.SetCurrentTexture(
            game_->player_.GetCurrentTexture() == "norm" ? "hurt" : "norm");
        Logger::Log("Set player texture to " +
                        game_->player_.GetCurrentTexture(),
                    INFO);
        break;

      default:
        break;
      }
    }
  }
}

const string MainLoop::ToString() const { return "Main Loop"; }

MainLoop::~MainLoop() {
  // dtor
}
<|endoftext|>


<commit_before>#define PUGIXML_NO_EXCEPTIONS
#define PUGIXML_HEADER_ONLY

#include <string>
#include "json/json.hpp"
#include "pugixml/src/pugixml.hpp"

using json = nlohmann::json;
using string = std::string;
using xquery = pugi::xpath_query;
using nodeset = pugi::xpath_node_set;

template <typename T>
void walk(T& doc, json& n, json& output, string key);

const string T_NUMBER = "number";
const string T_STRING = "string";
const string T_BOOLEAN = "boolean";

inline bool string_contains(string to_check, string prefix) {
  return to_check.size() >= prefix.size() &&
         to_check.compare(0, prefix.size(), prefix) == 0;
}

inline string get_return_type(string& path) {
  if (string_contains(path, "count(") || string_contains(path, "sum(") ||
      string_contains(path, "number(") || string_contains(path, "ceiling(") ||
      string_contains(path, "floor(") || string_contains(path, "round("))
    return T_NUMBER;

  if (string_contains(path, "boolean(")) return T_BOOLEAN;
  return T_STRING;
}

template <typename T>
bool seek_single_boolean(T& xnode, json& j) {
  string path = j;
  xquery query(path.c_str());
  return query.evaluate_boolean(xnode);
}

template <typename T>
string seek_single_string(T& xnode, json& j) {
  string path = j;
  if (path.empty()) {
    return "";
  } else if (path.find("#") != std::string::npos) {
    return path.substr(1, path.size());
  } else {
    xquery query(path.c_str());
    return query.evaluate_string(xnode);
  }
}

template <typename T>
double seek_single_number(T& xnode, json& j) {
  string path = j;
  xquery query(path.c_str());
  return query.evaluate_number(xnode);
}

template <typename T>
json seek_array(T& doc, json& node) {
  // a special case for backward compatible with xpath-object-transform
  if (node.empty()) {
    return json::array();
  }

  string base_path = node[0];
  xquery q(base_path.c_str());
  pugi::xpath_node_set nodes = q.evaluate_node_set(doc);
  json tmp = json::array();

  for (size_t i = 0; i < nodes.size(); ++i) {
    pugi::xpath_node n = nodes[i];
    auto inner = node[1];

    if (inner.is_object()) {
      json obj = json({});
      for (json::iterator it = inner.begin(); it != inner.end(); ++it) {
        walk(n, it.value(), obj, it.key());
      }

      tmp.push_back(obj);
    } else if (inner.is_string()) {
      string path = inner;
      string type = get_return_type((path));
      if (type == T_NUMBER) {
        tmp.push_back(seek_single_number(n, inner));
      }
      if (type == T_STRING) {
        tmp.push_back(seek_single_string(n, inner));
      }
      if (type == T_BOOLEAN) {
        tmp.push_back(seek_single_boolean(n, inner));
      }
    }
  }

  return tmp;
}

template <typename T>
json seek_object(T& doc, json& node) {
  auto output = json({});
  for (json::iterator it = node.begin(); it != node.end(); ++it) {
    string key = it.key();
    walk(doc, *it, output, key);
  }
  return output;
}

template <typename T>
void walk(T& doc, json& n, json& output, string key) {
  if (n.is_array()) {
    output[key] = seek_array(doc, n);
  } else if (n.is_object()) {
    output[key] = seek_object(doc, n);
  } else if (n.is_string()) {
    string path = n;
    string type = get_return_type(path);
    if (type == T_NUMBER) {
      output[key] = seek_single_number(doc, n);
    }
    if (type == T_STRING) {
      output[key] = seek_single_string(doc, n);
    }
    if (type == T_BOOLEAN) {
      output[key] = seek_single_boolean(doc, n);
    }
  }
}

string transform(string xml, string fmt) {
  pugi::xml_document doc;
  if (!doc.load_string(xml.c_str())) {
    return "";
  }

  auto j = json::parse(fmt);
  json result;

  for (json::iterator it = j.begin(); it != j.end(); ++it) {
    string key = it.key();
    auto& node = j[key];
    walk(doc, node, result, key);
  }

  return result.dump();
}<commit_msg>use enum for type check<commit_after>#define PUGIXML_NO_EXCEPTIONS
#define PUGIXML_HEADER_ONLY

#include <string>
#include "json/json.hpp"
#include "pugixml/src/pugixml.hpp"

using json = nlohmann::json;
using string = std::string;
using xquery = pugi::xpath_query;
using nodeset = pugi::xpath_node_set;

enum ReturnType { NUMBER, STRING, BOOLEAN };

template <typename T>
void walk(T& doc, json& n, json& output, string key);

inline bool string_contains(string to_check, string prefix) {
  return to_check.size() >= prefix.size() &&
         to_check.compare(0, prefix.size(), prefix) == 0;
}

inline ReturnType get_return_type(string& path) {
  if (string_contains(path, "count(") || string_contains(path, "sum(") ||
      string_contains(path, "number(") || string_contains(path, "ceiling(") ||
      string_contains(path, "floor(") || string_contains(path, "round("))
    return NUMBER;

  if (string_contains(path, "boolean("))
    return BOOLEAN;
  return STRING;
}

template <typename T>
bool seek_single_boolean(T& xnode, json& j) {
  string path = j;
  xquery query(path.c_str());
  return query.evaluate_boolean(xnode);
}

template <typename T>
string seek_single_string(T& xnode, json& j) {
  string path = j;
  if (path.empty()) {
    return "";
  } else if (path.find("#") != std::string::npos) {
    return path.substr(1, path.size());
  } else {
    xquery query(path.c_str());
    return query.evaluate_string(xnode);
  }
}

template <typename T>
double seek_single_number(T& xnode, json& j) {
  string path = j;
  xquery query(path.c_str());
  return query.evaluate_number(xnode);
}

template <typename T>
json seek_array(T& doc, json& node) {
  // a special case for backward compatible with xpath-object-transform
  if (node.empty()) {
    return json::array();
  }

  string base_path = node[0];
  xquery q(base_path.c_str());
  pugi::xpath_node_set nodes = q.evaluate_node_set(doc);
  json tmp = json::array();

  for (size_t i = 0; i < nodes.size(); ++i) {
    pugi::xpath_node n = nodes[i];
    auto inner = node[1];

    if (inner.is_object()) {
      json obj = json({});
      for (json::iterator it = inner.begin(); it != inner.end(); ++it) {
        walk(n, it.value(), obj, it.key());
      }

      tmp.push_back(obj);
    } else if (inner.is_string()) {
      string path = inner;
      ReturnType type = get_return_type((path));
      if (type == NUMBER) {
        tmp.push_back(seek_single_number(n, inner));
      }
      if (type == STRING) {
        tmp.push_back(seek_single_string(n, inner));
      }
      if (type == BOOLEAN) {
        tmp.push_back(seek_single_boolean(n, inner));
      }
    }
  }

  return tmp;
}

template <typename T>
json seek_object(T& doc, json& node) {
  auto output = json({});
  for (json::iterator it = node.begin(); it != node.end(); ++it) {
    string key = it.key();
    walk(doc, *it, output, key);
  }
  return output;
}

template <typename T>
void walk(T& doc, json& n, json& output, string key) {
  if (n.is_array()) {
    output[key] = seek_array(doc, n);
  } else if (n.is_object()) {
    output[key] = seek_object(doc, n);
  } else if (n.is_string()) {
    string path = n;
    ReturnType type = get_return_type(path);
    if (type == NUMBER) {
      output[key] = seek_single_number(doc, n);
    }
    if (type == STRING) {
      output[key] = seek_single_string(doc, n);
    }
    if (type == BOOLEAN) {
      output[key] = seek_single_boolean(doc, n);
    }
  }
}

string transform(string xml, string fmt) {
  pugi::xml_document doc;
  if (!doc.load_string(xml.c_str())) {
    return "";
  }

  auto j = json::parse(fmt);
  json result;

  for (json::iterator it = j.begin(); it != j.end(); ++it) {
    string key = it.key();
    auto& node = j[key];
    walk(doc, node, result, key);
  }

  return result.dump();
}<|endoftext|>


<commit_before>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrVkUtil.h"

#include "vk/GrVkGpu.h"
#include "SkSLCompiler.h"

bool GrPixelConfigToVkFormat(GrPixelConfig config, VkFormat* format) {
    VkFormat dontCare;
    if (!format) {
        format = &dontCare;
    }

    switch (config) {
        case kUnknown_GrPixelConfig:
            return false;
        case kRGBA_8888_GrPixelConfig:
            *format = VK_FORMAT_R8G8B8A8_UNORM;
            return true;
        case kBGRA_8888_GrPixelConfig:
            *format = VK_FORMAT_B8G8R8A8_UNORM;
            return true;
        case kSRGBA_8888_GrPixelConfig:
            *format = VK_FORMAT_R8G8B8A8_SRGB;
            return true;
        case kSBGRA_8888_GrPixelConfig:
            *format = VK_FORMAT_B8G8R8A8_SRGB;
            return true;
        case kRGBA_8888_sint_GrPixelConfig:
            *format = VK_FORMAT_R8G8B8A8_SINT;
            return true;
        case kRGB_565_GrPixelConfig:
            *format = VK_FORMAT_R5G6B5_UNORM_PACK16;
            return true;
        case kRGBA_4444_GrPixelConfig:
            // R4G4B4A4 is not required to be supported so we actually
            // store the data is if it was B4G4R4A4 and swizzle in shaders
            *format = VK_FORMAT_B4G4R4A4_UNORM_PACK16;
            return true;
        case kAlpha_8_GrPixelConfig:
            *format = VK_FORMAT_R8_UNORM;
            return true;
        case kGray_8_GrPixelConfig:
            *format = VK_FORMAT_R8_UNORM;
            return true;
        case kRGBA_float_GrPixelConfig:
            *format = VK_FORMAT_R32G32B32A32_SFLOAT;
            return true;
        case kRG_float_GrPixelConfig:
            *format = VK_FORMAT_R32G32_SFLOAT;
            return true;
        case kRGBA_half_GrPixelConfig:
            *format = VK_FORMAT_R16G16B16A16_SFLOAT;
            return true;
        case kAlpha_half_GrPixelConfig:
            *format = VK_FORMAT_R16_SFLOAT;
            return true;
    }
    SkFAIL("Unexpected config");
    return false;
}

GrPixelConfig GrVkFormatToPixelConfig(VkFormat format) {
    switch (format) {
        case VK_FORMAT_R8G8B8A8_UNORM:
            return kRGBA_8888_GrPixelConfig;
        case VK_FORMAT_B8G8R8A8_UNORM:
            return kBGRA_8888_GrPixelConfig;
        case VK_FORMAT_R8G8B8A8_SRGB:
            return kSRGBA_8888_GrPixelConfig;
        case VK_FORMAT_B8G8R8A8_SRGB:
            return kSBGRA_8888_GrPixelConfig;
        case VK_FORMAT_R8G8B8A8_SINT:
            return kRGBA_8888_sint_GrPixelConfig;
        case VK_FORMAT_R5G6B5_UNORM_PACK16:
            return kRGB_565_GrPixelConfig;
            break;
        case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
            // R4G4B4A4 is not required to be supported so we actually
            // store RGBA_4444 data as B4G4R4A4.
            return kRGBA_4444_GrPixelConfig;
        case VK_FORMAT_R8_UNORM:
            return kAlpha_8_GrPixelConfig;
        case VK_FORMAT_R32G32B32A32_SFLOAT:
            return kRGBA_float_GrPixelConfig;
        case VK_FORMAT_R32G32_SFLOAT:
            return kRG_float_GrPixelConfig;
        case VK_FORMAT_R16G16B16A16_SFLOAT:
            return kRGBA_half_GrPixelConfig;
        case VK_FORMAT_R16_SFLOAT:
            return kAlpha_half_GrPixelConfig;
        default:
            return kUnknown_GrPixelConfig;
    }
}

bool GrVkFormatIsSRGB(VkFormat format, VkFormat* linearFormat) {
    VkFormat linearFmt = format;
    switch (format) {
        case VK_FORMAT_R8_SRGB:
            linearFmt = VK_FORMAT_R8_UNORM;
            break;
        case VK_FORMAT_R8G8_SRGB:
            linearFmt = VK_FORMAT_R8G8_UNORM;
            break;
        case VK_FORMAT_R8G8B8_SRGB:
            linearFmt = VK_FORMAT_R8G8B8_UNORM;
            break;
        case VK_FORMAT_B8G8R8_SRGB:
            linearFmt = VK_FORMAT_B8G8R8_UNORM;
            break;
        case VK_FORMAT_R8G8B8A8_SRGB:
            linearFmt = VK_FORMAT_R8G8B8A8_UNORM;
            break;
        case VK_FORMAT_B8G8R8A8_SRGB:
            linearFmt = VK_FORMAT_B8G8R8A8_UNORM;
            break;
        case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
            linearFmt = VK_FORMAT_A8B8G8R8_UNORM_PACK32;
            break;
        case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
            linearFmt = VK_FORMAT_BC1_RGB_UNORM_BLOCK;
            break;
        case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
            linearFmt = VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
            break;
        case VK_FORMAT_BC2_SRGB_BLOCK:
            linearFmt = VK_FORMAT_BC2_UNORM_BLOCK;
            break;
        case VK_FORMAT_BC3_SRGB_BLOCK:
            linearFmt = VK_FORMAT_BC3_UNORM_BLOCK;
            break;
        case VK_FORMAT_BC7_SRGB_BLOCK:
            linearFmt = VK_FORMAT_BC7_UNORM_BLOCK;
            break;
        case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
            break;
        case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
            break;
        case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_4x4_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_5x4_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_5x5_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_6x5_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_6x6_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_8x5_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_8x6_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_8x8_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_10x5_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_10x6_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_10x8_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_10x10_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_12x10_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_12x12_UNORM_BLOCK;
            break;
        default:
            break;
    }
    if (linearFormat) {
        *linearFormat = linearFmt;
    }
    return (linearFmt != format);
}

bool GrSampleCountToVkSampleCount(uint32_t samples, VkSampleCountFlagBits* vkSamples) {
    switch (samples) {
        case 0: // fall through
        case 1:
            *vkSamples = VK_SAMPLE_COUNT_1_BIT;
            return true;
        case 2:
            *vkSamples = VK_SAMPLE_COUNT_2_BIT;
            return true;
        case 4:
            *vkSamples = VK_SAMPLE_COUNT_4_BIT;
            return true;
        case 8:
            *vkSamples = VK_SAMPLE_COUNT_8_BIT;
            return true;
        case 16:
            *vkSamples = VK_SAMPLE_COUNT_16_BIT;
            return true;
        case 32:
            *vkSamples = VK_SAMPLE_COUNT_32_BIT;
            return true;
        case 64:
            *vkSamples = VK_SAMPLE_COUNT_64_BIT;
            return true;
        default:
            return false;
    }
}

SkSL::Program::Kind vk_shader_stage_to_skiasl_kind(VkShaderStageFlagBits stage) {
    if (VK_SHADER_STAGE_VERTEX_BIT == stage) {
        return SkSL::Program::kVertex_Kind;
    }
    SkASSERT(VK_SHADER_STAGE_FRAGMENT_BIT == stage);
    return SkSL::Program::kFragment_Kind;
}

VkShaderStageFlagBits skiasl_kind_to_vk_shader_stage(SkSL::Program::Kind kind) {
    if (SkSL::Program::kVertex_Kind == kind) {
        return VK_SHADER_STAGE_VERTEX_BIT;
    }
    SkASSERT(SkSL::Program::kFragment_Kind == kind);
    return VK_SHADER_STAGE_FRAGMENT_BIT;
}

bool GrCompileVkShaderModule(const GrVkGpu* gpu,
                             const char* shaderString,
                             VkShaderStageFlagBits stage,
                             VkShaderModule* shaderModule,
                             VkPipelineShaderStageCreateInfo* stageInfo,
                             const SkSL::Program::Settings& settings,
                             SkSL::Program::Inputs* outInputs) {
    std::unique_ptr<SkSL::Program> program = gpu->shaderCompiler()->convertProgram(
                                                              vk_shader_stage_to_skiasl_kind(stage),
                                                              SkString(shaderString),
                                                              settings);
    if (!program) {
        SkDebugf("SkSL error:\n%s\n", gpu->shaderCompiler()->errorText().c_str());
        SkASSERT(false);
    }
    *outInputs = program->fInputs;
    SkSL::String code;
    if (!gpu->shaderCompiler()->toSPIRV(*program, &code)) {
        SkDebugf("%s\n", gpu->shaderCompiler()->errorText().c_str());
        return false;
    }

    VkShaderModuleCreateInfo moduleCreateInfo;
    memset(&moduleCreateInfo, 0, sizeof(VkShaderModuleCreateInfo));
    moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
    moduleCreateInfo.pNext = nullptr;
    moduleCreateInfo.flags = 0;
    moduleCreateInfo.codeSize = code.size();
    moduleCreateInfo.pCode = (const uint32_t*)code.c_str();

    VkResult err = GR_VK_CALL(gpu->vkInterface(), CreateShaderModule(gpu->device(),
                                                                     &moduleCreateInfo,
                                                                     nullptr,
                                                                     shaderModule));
    if (err) {
        return false;
    }

    memset(stageInfo, 0, sizeof(VkPipelineShaderStageCreateInfo));
    stageInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
    stageInfo->pNext = nullptr;
    stageInfo->flags = 0;
    stageInfo->stage = skiasl_kind_to_vk_shader_stage(program->fKind);
    stageInfo->module = *shaderModule;
    stageInfo->pName = "main";
    stageInfo->pSpecializationInfo = nullptr;

    return true;
}
<commit_msg>Add missing checks for geometry shader stages in GrVkUtil.cpp<commit_after>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrVkUtil.h"

#include "vk/GrVkGpu.h"
#include "SkSLCompiler.h"

bool GrPixelConfigToVkFormat(GrPixelConfig config, VkFormat* format) {
    VkFormat dontCare;
    if (!format) {
        format = &dontCare;
    }

    switch (config) {
        case kUnknown_GrPixelConfig:
            return false;
        case kRGBA_8888_GrPixelConfig:
            *format = VK_FORMAT_R8G8B8A8_UNORM;
            return true;
        case kBGRA_8888_GrPixelConfig:
            *format = VK_FORMAT_B8G8R8A8_UNORM;
            return true;
        case kSRGBA_8888_GrPixelConfig:
            *format = VK_FORMAT_R8G8B8A8_SRGB;
            return true;
        case kSBGRA_8888_GrPixelConfig:
            *format = VK_FORMAT_B8G8R8A8_SRGB;
            return true;
        case kRGBA_8888_sint_GrPixelConfig:
            *format = VK_FORMAT_R8G8B8A8_SINT;
            return true;
        case kRGB_565_GrPixelConfig:
            *format = VK_FORMAT_R5G6B5_UNORM_PACK16;
            return true;
        case kRGBA_4444_GrPixelConfig:
            // R4G4B4A4 is not required to be supported so we actually
            // store the data is if it was B4G4R4A4 and swizzle in shaders
            *format = VK_FORMAT_B4G4R4A4_UNORM_PACK16;
            return true;
        case kAlpha_8_GrPixelConfig:
            *format = VK_FORMAT_R8_UNORM;
            return true;
        case kGray_8_GrPixelConfig:
            *format = VK_FORMAT_R8_UNORM;
            return true;
        case kRGBA_float_GrPixelConfig:
            *format = VK_FORMAT_R32G32B32A32_SFLOAT;
            return true;
        case kRG_float_GrPixelConfig:
            *format = VK_FORMAT_R32G32_SFLOAT;
            return true;
        case kRGBA_half_GrPixelConfig:
            *format = VK_FORMAT_R16G16B16A16_SFLOAT;
            return true;
        case kAlpha_half_GrPixelConfig:
            *format = VK_FORMAT_R16_SFLOAT;
            return true;
    }
    SkFAIL("Unexpected config");
    return false;
}

GrPixelConfig GrVkFormatToPixelConfig(VkFormat format) {
    switch (format) {
        case VK_FORMAT_R8G8B8A8_UNORM:
            return kRGBA_8888_GrPixelConfig;
        case VK_FORMAT_B8G8R8A8_UNORM:
            return kBGRA_8888_GrPixelConfig;
        case VK_FORMAT_R8G8B8A8_SRGB:
            return kSRGBA_8888_GrPixelConfig;
        case VK_FORMAT_B8G8R8A8_SRGB:
            return kSBGRA_8888_GrPixelConfig;
        case VK_FORMAT_R8G8B8A8_SINT:
            return kRGBA_8888_sint_GrPixelConfig;
        case VK_FORMAT_R5G6B5_UNORM_PACK16:
            return kRGB_565_GrPixelConfig;
            break;
        case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
            // R4G4B4A4 is not required to be supported so we actually
            // store RGBA_4444 data as B4G4R4A4.
            return kRGBA_4444_GrPixelConfig;
        case VK_FORMAT_R8_UNORM:
            return kAlpha_8_GrPixelConfig;
        case VK_FORMAT_R32G32B32A32_SFLOAT:
            return kRGBA_float_GrPixelConfig;
        case VK_FORMAT_R32G32_SFLOAT:
            return kRG_float_GrPixelConfig;
        case VK_FORMAT_R16G16B16A16_SFLOAT:
            return kRGBA_half_GrPixelConfig;
        case VK_FORMAT_R16_SFLOAT:
            return kAlpha_half_GrPixelConfig;
        default:
            return kUnknown_GrPixelConfig;
    }
}

bool GrVkFormatIsSRGB(VkFormat format, VkFormat* linearFormat) {
    VkFormat linearFmt = format;
    switch (format) {
        case VK_FORMAT_R8_SRGB:
            linearFmt = VK_FORMAT_R8_UNORM;
            break;
        case VK_FORMAT_R8G8_SRGB:
            linearFmt = VK_FORMAT_R8G8_UNORM;
            break;
        case VK_FORMAT_R8G8B8_SRGB:
            linearFmt = VK_FORMAT_R8G8B8_UNORM;
            break;
        case VK_FORMAT_B8G8R8_SRGB:
            linearFmt = VK_FORMAT_B8G8R8_UNORM;
            break;
        case VK_FORMAT_R8G8B8A8_SRGB:
            linearFmt = VK_FORMAT_R8G8B8A8_UNORM;
            break;
        case VK_FORMAT_B8G8R8A8_SRGB:
            linearFmt = VK_FORMAT_B8G8R8A8_UNORM;
            break;
        case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
            linearFmt = VK_FORMAT_A8B8G8R8_UNORM_PACK32;
            break;
        case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
            linearFmt = VK_FORMAT_BC1_RGB_UNORM_BLOCK;
            break;
        case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
            linearFmt = VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
            break;
        case VK_FORMAT_BC2_SRGB_BLOCK:
            linearFmt = VK_FORMAT_BC2_UNORM_BLOCK;
            break;
        case VK_FORMAT_BC3_SRGB_BLOCK:
            linearFmt = VK_FORMAT_BC3_UNORM_BLOCK;
            break;
        case VK_FORMAT_BC7_SRGB_BLOCK:
            linearFmt = VK_FORMAT_BC7_UNORM_BLOCK;
            break;
        case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
            break;
        case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
            break;
        case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_4x4_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_5x4_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_5x5_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_6x5_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_6x6_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_8x5_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_8x6_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_8x8_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_10x5_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_10x6_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_10x8_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_10x10_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_12x10_UNORM_BLOCK;
            break;
        case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
            linearFmt = VK_FORMAT_ASTC_12x12_UNORM_BLOCK;
            break;
        default:
            break;
    }
    if (linearFormat) {
        *linearFormat = linearFmt;
    }
    return (linearFmt != format);
}

bool GrSampleCountToVkSampleCount(uint32_t samples, VkSampleCountFlagBits* vkSamples) {
    switch (samples) {
        case 0: // fall through
        case 1:
            *vkSamples = VK_SAMPLE_COUNT_1_BIT;
            return true;
        case 2:
            *vkSamples = VK_SAMPLE_COUNT_2_BIT;
            return true;
        case 4:
            *vkSamples = VK_SAMPLE_COUNT_4_BIT;
            return true;
        case 8:
            *vkSamples = VK_SAMPLE_COUNT_8_BIT;
            return true;
        case 16:
            *vkSamples = VK_SAMPLE_COUNT_16_BIT;
            return true;
        case 32:
            *vkSamples = VK_SAMPLE_COUNT_32_BIT;
            return true;
        case 64:
            *vkSamples = VK_SAMPLE_COUNT_64_BIT;
            return true;
        default:
            return false;
    }
}

SkSL::Program::Kind vk_shader_stage_to_skiasl_kind(VkShaderStageFlagBits stage) {
    if (VK_SHADER_STAGE_VERTEX_BIT == stage) {
        return SkSL::Program::kVertex_Kind;
    }
    if (VK_SHADER_STAGE_GEOMETRY_BIT == stage) {
        return SkSL::Program::kGeometry_Kind;
    }
    SkASSERT(VK_SHADER_STAGE_FRAGMENT_BIT == stage);
    return SkSL::Program::kFragment_Kind;
}

VkShaderStageFlagBits skiasl_kind_to_vk_shader_stage(SkSL::Program::Kind kind) {
    if (SkSL::Program::kVertex_Kind == kind) {
        return VK_SHADER_STAGE_VERTEX_BIT;
    }
    if (SkSL::Program::kGeometry_Kind == kind) {
        return VK_SHADER_STAGE_GEOMETRY_BIT;
    }
    SkASSERT(SkSL::Program::kFragment_Kind == kind);
    return VK_SHADER_STAGE_FRAGMENT_BIT;
}

bool GrCompileVkShaderModule(const GrVkGpu* gpu,
                             const char* shaderString,
                             VkShaderStageFlagBits stage,
                             VkShaderModule* shaderModule,
                             VkPipelineShaderStageCreateInfo* stageInfo,
                             const SkSL::Program::Settings& settings,
                             SkSL::Program::Inputs* outInputs) {
    std::unique_ptr<SkSL::Program> program = gpu->shaderCompiler()->convertProgram(
                                                              vk_shader_stage_to_skiasl_kind(stage),
                                                              SkString(shaderString),
                                                              settings);
    if (!program) {
        SkDebugf("SkSL error:\n%s\n", gpu->shaderCompiler()->errorText().c_str());
        SkASSERT(false);
    }
    *outInputs = program->fInputs;
    SkSL::String code;
    if (!gpu->shaderCompiler()->toSPIRV(*program, &code)) {
        SkDebugf("%s\n", gpu->shaderCompiler()->errorText().c_str());
        return false;
    }

    VkShaderModuleCreateInfo moduleCreateInfo;
    memset(&moduleCreateInfo, 0, sizeof(VkShaderModuleCreateInfo));
    moduleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
    moduleCreateInfo.pNext = nullptr;
    moduleCreateInfo.flags = 0;
    moduleCreateInfo.codeSize = code.size();
    moduleCreateInfo.pCode = (const uint32_t*)code.c_str();

    VkResult err = GR_VK_CALL(gpu->vkInterface(), CreateShaderModule(gpu->device(),
                                                                     &moduleCreateInfo,
                                                                     nullptr,
                                                                     shaderModule));
    if (err) {
        return false;
    }

    memset(stageInfo, 0, sizeof(VkPipelineShaderStageCreateInfo));
    stageInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
    stageInfo->pNext = nullptr;
    stageInfo->flags = 0;
    stageInfo->stage = skiasl_kind_to_vk_shader_stage(program->fKind);
    stageInfo->module = *shaderModule;
    stageInfo->pName = "main";
    stageInfo->pSpecializationInfo = nullptr;

    return true;
}
<|endoftext|>


<commit_before>#include "processingunit.h"

#include "alignment.h"
#include "desutils.h"

namespace descrack {
namespace opencl {
namespace gpu {

static constexpr std::size_t MAX_FOUND_KEYS = 16;

ProcessingUnit::ProcessingUnit(const DeviceContext *context,
                               std::size_t bitsThread)
    : context(context), cmdQueue(context->getCommandQueue())
{
    auto programContext = context->getProgramContext();
    auto dlContext = programContext->getDeviceListContext();
    auto &clContext = dlContext->getClContext();
    auto &device = context->getDevice();

    auto bitsGlobal = programContext->getBitsGlobal();

    kernel = cl::Kernel(programContext->getProgram(), "des_kernel");

    items = std::size_t(1) << (bitsGlobal - bitsThread);
    resultBits = programContext->getVectorLevel() + bitsGlobal;

    groupSize = std::min(items, kernel.getWorkGroupInfo<CL_KERNEL_WORK_GROUP_SIZE>(device));
    groupCount = BLOCK_COUNT(groupSize, items);

    cdBaseBufferSize = (56 - bitsGlobal) * programContext->getVectorBytes();
    resultBufferSize = (MAX_FOUND_KEYS + 1) * sizeof(cl_uint);

    cdBaseBuffer = cl::Buffer(clContext, CL_MEM_READ_ONLY, cdBaseBufferSize);
    resultBuffer = cl::Buffer(clContext, CL_MEM_WRITE_ONLY, resultBufferSize);

    kernel.setArg<cl::Buffer>(0, programContext->getRefInputBuffer());
    kernel.setArg<cl::Buffer>(1, programContext->getRefOutputBuffer());
    kernel.setArg<cl::Buffer>(2, cdBaseBuffer);
    kernel.setArg<cl::Buffer>(3, resultBuffer);
    kernel.setArg<cl_uint>   (4, static_cast<cl_uint>(bitsThread));
}

void ProcessingUnit::setBatch(std::uint_fast64_t index)
{
    batch = index;
    void *hostBuffer = cmdQueue.enqueueMapBuffer(
                cdBaseBuffer, true, CL_MAP_WRITE,
                0, cdBaseBufferSize);

    auto programContext = context->getProgramContext();
    programContext->writeCdBase(hostBuffer, index);

    cmdQueue.enqueueUnmapMemObject(cdBaseBuffer, hostBuffer);
}

bool ProcessingUnit::getResult(std::uint_fast64_t &key)
{
    auto mappedResultBuffer = static_cast<cl_uint *>(
                cmdQueue.enqueueMapBuffer(
                    resultBuffer, true, CL_MAP_READ, 0,
                    resultBufferSize, nullptr, &event));

    // FIXME: allow reporting multiple found keys (just in case)
    bool res = false;
    auto count = mappedResultBuffer[0];
    if (count > 0) {
        std::uint_fast64_t cd = (batch << resultBits) |
                std::uint_fast64_t(mappedResultBuffer[1]);
        key = DesUtils::keyFromCd(cd);
        res = true;
    }
    cmdQueue.enqueueUnmapMemObject(resultBuffer, mappedResultBuffer);
    return res;
}

void ProcessingUnit::beginProcessing()
{
    cmdQueue.enqueueNDRangeKernel(
                kernel, cl::NullRange, cl::NDRange(items), cl::NDRange(groupSize),
                nullptr, &event);
}

void ProcessingUnit::endProcessing()
{
    event.wait();
    event = cl::Event();
}

} // namespace gpu
} // namespace opencl
} // namespace descrack
<commit_msg>Fixed a copy-paste mistake.<commit_after>#include "processingunit.h"

#include "alignment.h"
#include "desutils.h"

namespace descrack {
namespace opencl {
namespace gpu {

static constexpr std::size_t MAX_FOUND_KEYS = 16;

ProcessingUnit::ProcessingUnit(const DeviceContext *context,
                               std::size_t bitsThread)
    : context(context), cmdQueue(context->getCommandQueue())
{
    auto programContext = context->getProgramContext();
    auto dlContext = programContext->getDeviceListContext();
    auto &clContext = dlContext->getClContext();
    auto &device = context->getDevice();

    auto bitsGlobal = programContext->getBitsGlobal();

    kernel = cl::Kernel(programContext->getProgram(), "des_kernel");

    items = std::size_t(1) << (bitsGlobal - bitsThread);
    resultBits = programContext->getVectorLevel() + bitsGlobal;

    groupSize = std::min(items, kernel.getWorkGroupInfo<CL_KERNEL_WORK_GROUP_SIZE>(device));
    groupCount = BLOCK_COUNT(groupSize, items);

    cdBaseBufferSize = (56 - bitsGlobal) * programContext->getVectorBytes();
    resultBufferSize = (MAX_FOUND_KEYS + 1) * sizeof(cl_uint);

    cdBaseBuffer = cl::Buffer(clContext, CL_MEM_READ_ONLY, cdBaseBufferSize);
    resultBuffer = cl::Buffer(clContext, CL_MEM_WRITE_ONLY, resultBufferSize);

    kernel.setArg<cl::Buffer>(0, programContext->getRefInputBuffer());
    kernel.setArg<cl::Buffer>(1, programContext->getRefOutputBuffer());
    kernel.setArg<cl::Buffer>(2, cdBaseBuffer);
    kernel.setArg<cl::Buffer>(3, resultBuffer);
    kernel.setArg<cl_uint>   (4, static_cast<cl_uint>(bitsThread));
}

void ProcessingUnit::setBatch(std::uint_fast64_t index)
{
    batch = index;
    void *hostBuffer = cmdQueue.enqueueMapBuffer(
                cdBaseBuffer, true, CL_MAP_WRITE,
                0, cdBaseBufferSize);

    auto programContext = context->getProgramContext();
    programContext->writeCdBase(hostBuffer, index);

    cmdQueue.enqueueUnmapMemObject(cdBaseBuffer, hostBuffer);
}

bool ProcessingUnit::getResult(std::uint_fast64_t &key)
{
    auto mappedResultBuffer = static_cast<cl_uint *>(
                cmdQueue.enqueueMapBuffer(
                    resultBuffer, true, CL_MAP_READ,
                    0, resultBufferSize));

    // FIXME: allow reporting multiple found keys (just in case)
    bool res = false;
    auto count = mappedResultBuffer[0];
    if (count > 0) {
        std::uint_fast64_t cd = (batch << resultBits) |
                std::uint_fast64_t(mappedResultBuffer[1]);
        key = DesUtils::keyFromCd(cd);
        res = true;
    }
    cmdQueue.enqueueUnmapMemObject(resultBuffer, mappedResultBuffer);
    return res;
}

void ProcessingUnit::beginProcessing()
{
    cmdQueue.enqueueNDRangeKernel(
                kernel, cl::NullRange, cl::NDRange(items), cl::NDRange(groupSize),
                nullptr, &event);
}

void ProcessingUnit::endProcessing()
{
    event.wait();
    event = cl::Event();
}

} // namespace gpu
} // namespace opencl
} // namespace descrack
<|endoftext|>