<commit_before>#include <shader_validation.hpp>

#include <sigma/graphics/shader.hpp>

#ifdef USE_GLSLANG
#include <glslang/Public/ShaderLang.h>
#include <regex>

static const TBuiltInResource default_resources = {
    32, // MaxLights
    6, // MaxClipPlanes
    32, // MaxTextureUnits
    32, // MaxTextureCoords
    64, // MaxVertexAttribs
    4096, // MaxVertexUniformComponents
    64, // MaxVaryingFloats
    32, // MaxVertexTextureImageUnits
    80, // MaxCombinedTextureImageUnits
    32, // MaxTextureImageUnits
    4096, // MaxFragmentUniformComponents
    32, // MaxDrawBuffers
    128, // MaxVertexUniformVectors
    8, // MaxVaryingVectors
    16, // MaxFragmentUniformVectors
    16, // MaxVertexOutputVectors
    15, // MaxFragmentInputVectors
    -8, // MinProgramTexelOffset
    7, // MaxProgramTexelOffset
    8, // MaxClipDistances
    65535, // MaxComputeWorkGroupCountX
    65535, // MaxComputeWorkGroupCountY
    65535, // MaxComputeWorkGroupCountZ
    1024, // MaxComputeWorkGroupSizeX
    1024, // MaxComputeWorkGroupSizeY
    64, // MaxComputeWorkGroupSizeZ
    1024, // MaxComputeUniformComponents
    16, // MaxComputeTextureImageUnits
    8, // MaxComputeImageUniforms
    8, // MaxComputeAtomicCounters
    1, // MaxComputeAtomicCounterBuffers
    60, // MaxVaryingComponents
    64, // MaxVertexOutputComponents
    64, // MaxGeometryInputComponents
    128, // MaxGeometryOutputComponents
    128, // MaxFragmentInputComponents
    8, // MaxImageUnits
    8, // MaxCombinedImageUnitsAndFragmentOutputs
    8, // MaxCombinedShaderOutputResources
    0, // MaxImageSamples
    0, // MaxVertexImageUniforms
    0, // MaxTessControlImageUniforms
    0, // MaxTessEvaluationImageUniforms
    0, // MaxGeometryImageUniforms
    8, // MaxFragmentImageUniforms
    8, // MaxCombinedImageUniforms
    16, // MaxGeometryTextureImageUnits
    256, // MaxGeometryOutputVertices
    1024, // MaxGeometryTotalOutputComponents
    1024, // MaxGeometryUniformComponents
    64, // MaxGeometryVaryingComponents
    128, // MaxTessControlInputComponents
    128, // MaxTessControlOutputComponents
    16, // MaxTessControlTextureImageUnits
    1024, // MaxTessControlUniformComponents
    4096, // MaxTessControlTotalOutputComponents
    128, // MaxTessEvaluationInputComponents
    128, // MaxTessEvaluationOutputComponents
    16, // MaxTessEvaluationTextureImageUnits
    1024, // MaxTessEvaluationUniformComponents
    120, // MaxTessPatchComponents
    32, // MaxPatchVertices
    64, // MaxTessGenLevel
    16, // MaxViewports
    0, // MaxVertexAtomicCounters
    0, // MaxTessControlAtomicCounters
    0, // MaxTessEvaluationAtomicCounters
    0, // MaxGeometryAtomicCounters
    8, // MaxFragmentAtomicCounters
    8, // MaxCombinedAtomicCounters
    1, // MaxAtomicCounterBindings
    0, // MaxVertexAtomicCounterBuffers
    0, // MaxTessControlAtomicCounterBuffers
    0, // MaxTessEvaluationAtomicCounterBuffers
    0, // MaxGeometryAtomicCounterBuffers
    1, // MaxFragmentAtomicCounterBuffers
    1, // MaxCombinedAtomicCounterBuffers
    16384, // MaxAtomicCounterBufferSize
    4, // MaxTransformFeedbackBuffers
    64, // MaxTransformFeedbackInterleavedComponents
    8, // MaxCullDistances
    8, // MaxCombinedClipAndCullDistances
    4, // MaxSamples
    // limits
    {
        1, // nonInductiveForLoops
        1, // whileLoops
        1, // doWhileLoops
        1, // generalUniformIndexing
        1, // generalAttributeMatrixVectorIndexing
        1, // generalVaryingIndexing
        1, // generalSamplerIndexing
        1, // generalVariableIndexing
        1, // generalConstantMatrixVectorIndexing
    }
};

struct glsl_process {
    glsl_process()
    {
        glslang::InitializeProcess();
    }
    ~glsl_process()
    {
        glslang::FinalizeProcess();
    }
};
bool sigma::validate_shader(const graphics::shader_data& shader, std::vector<boost::filesystem::path> source_filenames)
{
    glsl_process validation_process;

    EShLanguage glslLangType;
    switch (shader.type) {
    case graphics::shader_type::vertex: {
        glslLangType = EShLangVertex;
        break;
    }
    case graphics::shader_type::fragment: {
        glslLangType = EShLangFragment;
        break;
    }
    case graphics::shader_type::geometry: {
        glslLangType = EShLangGeometry;
        break;
    }
    case graphics::shader_type::header: {
        return false;
        break;
    }
    }

    glslang::TShader glslShader{ glslLangType };
    const char* src = shader.source.c_str();
    glslShader.setStrings(&src, 1);

    if (!glslShader.parse(&default_resources, 330, true, EShMsgDefault)) {

        std::string error_message = glslShader.getInfoLog();

        std::regex error_regex("error\\s*:\\s*(\\d+):(\\d+):(.*)", std::regex_constants::icase);
        std::smatch res;

        const auto begin_iterator = std::sregex_iterator(error_message.cbegin(), error_message.cend(), error_regex);
        const auto end_iterator = std::sregex_iterator();

        for (auto it = begin_iterator; it != end_iterator; ++it) {
            auto match = *it;
            std::cerr << source_filenames[std::stoi(match[1])].string() << "(" << match[2] << "): error :" << match[3] << '\n'; // MSVC output
        }

        return false;
    }

    return true;
}

#else // Do not use glslang

bool sigma::validate_shader(const graphics::shader_data& shader, std::vector<boost::filesystem::path> source_filenames)
{
    return true;
}

#endif // USE_GLSLANG
<commit_msg>Must always validate shaders when compiling.<commit_after>#include <shader_validation.hpp>

#include <sigma/graphics/shader.hpp>

#include <glslang/Public/ShaderLang.h>
#include <regex>

static const TBuiltInResource default_resources = {
    32, // MaxLights
    6, // MaxClipPlanes
    32, // MaxTextureUnits
    32, // MaxTextureCoords
    64, // MaxVertexAttribs
    4096, // MaxVertexUniformComponents
    64, // MaxVaryingFloats
    32, // MaxVertexTextureImageUnits
    80, // MaxCombinedTextureImageUnits
    32, // MaxTextureImageUnits
    4096, // MaxFragmentUniformComponents
    32, // MaxDrawBuffers
    128, // MaxVertexUniformVectors
    8, // MaxVaryingVectors
    16, // MaxFragmentUniformVectors
    16, // MaxVertexOutputVectors
    15, // MaxFragmentInputVectors
    -8, // MinProgramTexelOffset
    7, // MaxProgramTexelOffset
    8, // MaxClipDistances
    65535, // MaxComputeWorkGroupCountX
    65535, // MaxComputeWorkGroupCountY
    65535, // MaxComputeWorkGroupCountZ
    1024, // MaxComputeWorkGroupSizeX
    1024, // MaxComputeWorkGroupSizeY
    64, // MaxComputeWorkGroupSizeZ
    1024, // MaxComputeUniformComponents
    16, // MaxComputeTextureImageUnits
    8, // MaxComputeImageUniforms
    8, // MaxComputeAtomicCounters
    1, // MaxComputeAtomicCounterBuffers
    60, // MaxVaryingComponents
    64, // MaxVertexOutputComponents
    64, // MaxGeometryInputComponents
    128, // MaxGeometryOutputComponents
    128, // MaxFragmentInputComponents
    8, // MaxImageUnits
    8, // MaxCombinedImageUnitsAndFragmentOutputs
    8, // MaxCombinedShaderOutputResources
    0, // MaxImageSamples
    0, // MaxVertexImageUniforms
    0, // MaxTessControlImageUniforms
    0, // MaxTessEvaluationImageUniforms
    0, // MaxGeometryImageUniforms
    8, // MaxFragmentImageUniforms
    8, // MaxCombinedImageUniforms
    16, // MaxGeometryTextureImageUnits
    256, // MaxGeometryOutputVertices
    1024, // MaxGeometryTotalOutputComponents
    1024, // MaxGeometryUniformComponents
    64, // MaxGeometryVaryingComponents
    128, // MaxTessControlInputComponents
    128, // MaxTessControlOutputComponents
    16, // MaxTessControlTextureImageUnits
    1024, // MaxTessControlUniformComponents
    4096, // MaxTessControlTotalOutputComponents
    128, // MaxTessEvaluationInputComponents
    128, // MaxTessEvaluationOutputComponents
    16, // MaxTessEvaluationTextureImageUnits
    1024, // MaxTessEvaluationUniformComponents
    120, // MaxTessPatchComponents
    32, // MaxPatchVertices
    64, // MaxTessGenLevel
    16, // MaxViewports
    0, // MaxVertexAtomicCounters
    0, // MaxTessControlAtomicCounters
    0, // MaxTessEvaluationAtomicCounters
    0, // MaxGeometryAtomicCounters
    8, // MaxFragmentAtomicCounters
    8, // MaxCombinedAtomicCounters
    1, // MaxAtomicCounterBindings
    0, // MaxVertexAtomicCounterBuffers
    0, // MaxTessControlAtomicCounterBuffers
    0, // MaxTessEvaluationAtomicCounterBuffers
    0, // MaxGeometryAtomicCounterBuffers
    1, // MaxFragmentAtomicCounterBuffers
    1, // MaxCombinedAtomicCounterBuffers
    16384, // MaxAtomicCounterBufferSize
    4, // MaxTransformFeedbackBuffers
    64, // MaxTransformFeedbackInterleavedComponents
    8, // MaxCullDistances
    8, // MaxCombinedClipAndCullDistances
    4, // MaxSamples
    // limits
    {
        1, // nonInductiveForLoops
        1, // whileLoops
        1, // doWhileLoops
        1, // generalUniformIndexing
        1, // generalAttributeMatrixVectorIndexing
        1, // generalVaryingIndexing
        1, // generalSamplerIndexing
        1, // generalVariableIndexing
        1, // generalConstantMatrixVectorIndexing
    }
};

struct glsl_process {
    glsl_process()
    {
        glslang::InitializeProcess();
    }
    ~glsl_process()
    {
        glslang::FinalizeProcess();
    }
};
bool sigma::validate_shader(const graphics::shader_data& shader, std::vector<boost::filesystem::path> source_filenames)
{
    glsl_process validation_process;

    EShLanguage glslLangType;
    switch (shader.type) {
    case graphics::shader_type::vertex: {
        glslLangType = EShLangVertex;
        break;
    }
    case graphics::shader_type::fragment: {
        glslLangType = EShLangFragment;
        break;
    }
    case graphics::shader_type::geometry: {
        glslLangType = EShLangGeometry;
        break;
    }
    case graphics::shader_type::header: {
        return false;
        break;
    }
    }

    glslang::TShader glslShader{ glslLangType };
    const char* src = shader.source.c_str();
    glslShader.setStrings(&src, 1);

    if (!glslShader.parse(&default_resources, 330, true, EShMsgDefault)) {

        std::string error_message = glslShader.getInfoLog();

        std::regex error_regex("error\\s*:\\s*(\\d+):(\\d+):(.*)", std::regex_constants::icase);
        std::smatch res;

        const auto begin_iterator = std::sregex_iterator(error_message.cbegin(), error_message.cend(), error_regex);
        const auto end_iterator = std::sregex_iterator();

        for (auto it = begin_iterator; it != end_iterator; ++it) {
            auto match = *it;
            std::cerr << source_filenames[std::stoi(match[1])].string() << "(" << match[2] << "): error :" << match[3] << '\n'; // MSVC output
        }

        return false;
    }

    return true;
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2014, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

#include <osquery/logger.h>
#include <osquery/tables/applications/browser_utils.h>

#include "osquery/tables/system/system_utils.h"

namespace osquery {
namespace tables {

#define kManifestFile "/manifest.json"

const std::map<std::string, std::string> kExtensionKeys = {
    {"version", "version"},
    {"name", "name"},
    {"description", "description"},
    {"default_locale", "locale"},
    {"update_url", "update_url"},
    {"author", "author"},
    {"background.persistent", "persistent"}
};

void genExtension(const std::string& uid,
                  const std::string& path,
                  QueryData& results) {
  std::string json_data;
  if (!readFile(path + kManifestFile, json_data).ok()) {
    VLOG(1) << "Could not read file: " << path + kManifestFile;
    return;
  }

  // Read the extensions data into a JSON blob, then property tree.
  pt::ptree tree;
  std::stringstream json_stream;
  json_stream << json_data;
  try {
    pt::read_json(json_stream, tree);
  } catch (const pt::json_parser::json_parser_error& e) {
    VLOG(1) << "Could not parse JSON from: " << path + kManifestFile;
    return;
  }

  Row r;
  r["uid"] = uid;
  // Most of the keys are in the top-level JSON dictionary.
  for (const auto& it : kExtensionKeys) {
    r[it.second] = tree.get<std::string>(it.first, "");

    // Convert JSON bool-types to an integer.
    if (r[it.second] == "true") {
      r[it.second] = INTEGER(1);
    } else if (r[it.second] == "false") {
      r[it.second] = INTEGER(0);
    }
  }

  // Set the default persistence setting to false
  if (r.at("persistent") == "") {
    r["persistent"] = INTEGER(0);
  }

  r["identifier"] = fs::path(path).parent_path().leaf().string();
  r["path"] = path;
  results.push_back(r);
}

QueryData genChromeBasedExtensions(QueryContext& context,
                                   const fs::path& sub_dir) {
  QueryData results;

  auto users = usersFromContext(context);
  for (const auto& row : users) {
    if (row.count("uid") > 0 && row.count("directory") > 0) {
      // For each user, enumerate all of their chrome profiles.
      std::vector<std::string> profiles;
      fs::path extension_path = row.at("directory") / sub_dir;
      if (!resolveFilePattern(extension_path, profiles, GLOB_FOLDERS).ok()) {
        continue;
      }

      // For each profile list each extension in the Extensions directory.
      std::vector<std::string> extensions;
      for (const auto& profile : profiles) {
        listDirectoriesInDirectory(profile, extensions);
      }

      // Generate an addons list from their extensions JSON.
      std::vector<std::string> versions;
      for (const auto& extension : extensions) {
        listDirectoriesInDirectory(extension, versions);
      }

      // Extensions use /<EXTENSION>/<VERSION>/manifest.json.
      for (const auto& version : versions) {
        genExtension(row.at("uid"), version, results);
      }
    }
  }

  return results;
}
}
}
<commit_msg>Make chrome extension identifiers easier to extract<commit_after>/*
 *  Copyright (c) 2014, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

#include <osquery/logger.h>
#include <osquery/tables/applications/browser_utils.h>

#include "osquery/tables/system/system_utils.h"

namespace osquery {
namespace tables {

#define kManifestFile "/manifest.json"

const std::map<std::string, std::string> kExtensionKeys = {
    {"version", "version"},
    {"name", "name"},
    {"description", "description"},
    {"default_locale", "locale"},
    {"update_url", "update_url"},
    {"author", "author"},
    {"background.persistent", "persistent"}};

void genExtension(const std::string& uid,
                  const std::string& path,
                  QueryData& results) {
  std::string json_data;
  if (!readFile(path + kManifestFile, json_data).ok()) {
    VLOG(1) << "Could not read file: " << path + kManifestFile;
    return;
  }

  // Read the extensions data into a JSON blob, then property tree.
  pt::ptree tree;
  std::stringstream json_stream;
  json_stream << json_data;
  try {
    pt::read_json(json_stream, tree);
  } catch (const pt::json_parser::json_parser_error& e) {
    VLOG(1) << "Could not parse JSON from: " << path + kManifestFile;
    return;
  }

  Row r;
  r["uid"] = uid;
  // Most of the keys are in the top-level JSON dictionary.
  for (const auto& it : kExtensionKeys) {
    r[it.second] = tree.get<std::string>(it.first, "");

    // Convert JSON bool-types to an integer.
    if (r[it.second] == "true") {
      r[it.second] = INTEGER(1);
    } else if (r[it.second] == "false") {
      r[it.second] = INTEGER(0);
    }
  }

  // Set the default persistence setting to false
  if (r.at("persistent") == "") {
    r["persistent"] = INTEGER(0);
  }

  r["identifier"] = fs::path(path).parent_path().parent_path().leaf().string();
  r["path"] = path;
  results.push_back(r);
}

QueryData genChromeBasedExtensions(QueryContext& context,
                                   const fs::path& sub_dir) {
  QueryData results;

  auto users = usersFromContext(context);
  for (const auto& row : users) {
    if (row.count("uid") > 0 && row.count("directory") > 0) {
      // For each user, enumerate all of their chrome profiles.
      std::vector<std::string> profiles;
      fs::path extension_path = row.at("directory") / sub_dir;
      if (!resolveFilePattern(extension_path, profiles, GLOB_FOLDERS).ok()) {
        continue;
      }

      // For each profile list each extension in the Extensions directory.
      std::vector<std::string> extensions;
      for (const auto& profile : profiles) {
        listDirectoriesInDirectory(profile, extensions);
      }

      // Generate an addons list from their extensions JSON.
      std::vector<std::string> versions;
      for (const auto& extension : extensions) {
        listDirectoriesInDirectory(extension, versions);
      }

      // Extensions use /<EXTENSION>/<VERSION>/manifest.json.
      for (const auto& version : versions) {
        genExtension(row.at("uid"), version, results);
      }
    }
  }

  return results;
}
}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: ZipPackageEntry.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: mtg $ $Date: 2001-10-26 21:55:47 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifndef _ZIP_PACKAGE_ENTRY_HXX
#define _ZIP_PACKAGE_ENTRY_HXX

#ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_
#include <com/sun/star/container/XChild.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMED_HPP_
#include <com/sun/star/container/XNamed.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
#include <com/sun/star/container/XNameContainer.hpp>
#endif
#ifndef _ZIP_ENTRY_HXX_
#include <ZipEntry.hxx>
#endif

class ZipPackageFolder;

class ZipPackageEntry : public com::sun::star::container::XNamed,
                        public com::sun::star::container::XChild,
                        public com::sun::star::lang::XUnoTunnel,
                        public com::sun::star::beans::XPropertySet
{
protected:
    bool mbIsFolder:1;
    com::sun::star::uno::Reference < com::sun::star::container::XNameContainer > xParent;
    ::rtl::OUString     sMediaType;
    ZipPackageFolder * pParent;
public:
    ZipEntry aEntry;
    ZipPackageEntry ( bool bNewFolder );
    virtual ~ZipPackageEntry( void );

    ::rtl::OUString & GetMediaType () { return sMediaType; }
    void SetMediaType ( ::rtl::OUString & sNewType) { sMediaType = sNewType; }
    void doSetParent ( ZipPackageFolder * pNewParent, sal_Bool bInsert );
    bool IsFolder ( ) { return mbIsFolder; }
    ZipPackageFolder* GetParent ( ) { return pParent; }
    void SetFolder ( bool bSetFolder ) { mbIsFolder = bSetFolder; }

    void clearParent ( void )
    {
        xParent.clear();
    }
    // XNamed
    virtual ::rtl::OUString SAL_CALL getName(  )
        throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL setName( const ::rtl::OUString& aName )
        throw(::com::sun::star::uno::RuntimeException);
    // XChild
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getParent(  )
        throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL setParent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& Parent )
        throw(::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException);
    // XUnoTunnel
    virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier )
        throw(::com::sun::star::uno::RuntimeException) = 0;
    // XPropertySet
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo(  )
        throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue )
        throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) = 0;
    virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName )
        throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) = 0;
    virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener )
        throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener )
        throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL addVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener )
        throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL removeVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener )
        throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
};
#endif
<commit_msg>#94679# support XTypeProvider and XServiceInfo<commit_after>/*************************************************************************
 *
 *  $RCSfile: ZipPackageEntry.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: mtg $ $Date: 2001-11-15 20:39:25 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifndef _ZIP_PACKAGE_ENTRY_HXX
#define _ZIP_PACKAGE_ENTRY_HXX

#ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_
#include <com/sun/star/container/XChild.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMED_HPP_
#include <com/sun/star/container/XNamed.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
#include <com/sun/star/container/XNameContainer.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XPSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif
#ifndef _ZIP_ENTRY_HXX_
#include <ZipEntry.hxx>
#endif
#ifndef _CPPUHELPER_IMPLBASE5_HXX_
#include <cppuhelper/implbase5.hxx>
#endif

class ZipPackageFolder;

class ZipPackageEntry : public cppu::WeakImplHelper5
<
    com::sun::star::container::XNamed,
    com::sun::star::container::XChild,
    com::sun::star::lang::XUnoTunnel,
    com::sun::star::beans::XPropertySet,
    com::sun::star::lang::XServiceInfo
>
{
protected:
    bool mbIsFolder:1;
    com::sun::star::uno::Reference < com::sun::star::container::XNameContainer > xParent;
    ::rtl::OUString     sMediaType;
    ZipPackageFolder * pParent;
public:
    ZipEntry aEntry;
    ZipPackageEntry ( bool bNewFolder = sal_False );
    virtual ~ZipPackageEntry( void );

    ::rtl::OUString & GetMediaType () { return sMediaType; }
    void SetMediaType ( ::rtl::OUString & sNewType) { sMediaType = sNewType; }
    void doSetParent ( ZipPackageFolder * pNewParent, sal_Bool bInsert );
    bool IsFolder ( ) { return mbIsFolder; }
    ZipPackageFolder* GetParent ( ) { return pParent; }
    void SetFolder ( bool bSetFolder ) { mbIsFolder = bSetFolder; }

    void clearParent ( void )
    {
        xParent.clear();
    }
    // XNamed
    virtual ::rtl::OUString SAL_CALL getName(  )
        throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL setName( const ::rtl::OUString& aName )
        throw(::com::sun::star::uno::RuntimeException);
    // XChild
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getParent(  )
        throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL setParent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& Parent )
        throw(::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException);
    // XUnoTunnel
    virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier )
        throw(::com::sun::star::uno::RuntimeException) = 0;
    // XPropertySet
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo(  )
        throw(::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue )
        throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) = 0;
    virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName )
        throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) = 0;
    virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener )
        throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener )
        throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL addVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener )
        throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
    virtual void SAL_CALL removeVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener )
        throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
};
#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <errno.h>
#include <stdlib.h>
#include <string.h>

#include <algorithm>
#include <string>

#include "native_client/src/include/nacl_scoped_ptr.h"
#include "native_client/src/include/portability_sockets.h"
#include "native_client/src/shared/platform/nacl_log.h"
#include "native_client/src/trusted/debug_stub/platform.h"
#include "native_client/src/trusted/debug_stub/transport.h"
#include "native_client/src/trusted/debug_stub/util.h"
#include "native_client/src/trusted/service_runtime/sel_ldr.h"

using gdb_rsp::stringvec;
using gdb_rsp::StringSplit;

namespace port {

typedef int socklen_t;

class Transport : public ITransport {
 public:
  Transport()
    : buf_(new char[kBufSize]),
      pos_(0),
      size_(0) {
    handle_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
#if NACL_WINDOWS
    CreateSocketEvent();
#endif
  }

  explicit Transport(NaClSocketHandle s)
    : buf_(new char[kBufSize]),
      pos_(0),
      size_(0),
      handle_(s) {
#if NACL_WINDOWS
    CreateSocketEvent();
#endif
  }

  ~Transport() {
    if (handle_ != NACL_INVALID_SOCKET) NaClCloseSocket(handle_);
#if NACL_WINDOWS
    if (!WSACloseEvent(socket_event_)) {
      NaClLog(LOG_FATAL,
              "Transport::~Transport: Failed to close socket event\n");
    }
#endif
  }

#if NACL_WINDOWS
  void CreateSocketEvent() {
    socket_event_ = WSACreateEvent();
    if (socket_event_ == WSA_INVALID_EVENT) {
      NaClLog(LOG_FATAL,
              "Transport::CreateSocketEvent: Failed to create socket event\n");
    }
    if (WSAEventSelect(handle_, socket_event_, FD_READ) == SOCKET_ERROR) {
      NaClLog(LOG_FATAL,
              "Transport::CreateSocketEvent: Failed to bind event to socket\n");
    }
  }
#endif

  // Read from this transport, return true on success.
  virtual bool Read(void *ptr, int32_t len);

  // Write to this transport, return true on success.
  virtual bool Write(const void *ptr, int32_t len);

  // Return true if there is data to read.
  virtual bool IsDataAvailable() {
    if (pos_ < size_) {
      return true;
    }
    fd_set fds;

    FD_ZERO(&fds);
    FD_SET(handle_, &fds);

    // We want a "non-blocking" check
    struct timeval timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = 0;

    // Check if this file handle can select on read
    int cnt = select(static_cast<int>(handle_) + 1, &fds, 0, 0, &timeout);

    // If we are ready, or if there is an error.  We return true
    // on error, to let the next IO request fail.
    if (cnt != 0) return true;

    return false;
  }

  virtual void WaitForDebugStubEvent(struct NaClApp *nap,
                                     bool ignore_input_from_gdb);

// On windows, the header that defines this has other definition
// colitions, so we define it outselves just in case
#ifndef SD_BOTH
#define SD_BOTH 2
#endif

  virtual void Disconnect() {
    // Shutdown the conneciton in both diections.  This should
    // always succeed, and nothing we can do if this fails.
    (void) ::shutdown(handle_, SD_BOTH);
  }

 protected:
  // Copy buffered data to *dst up to len bytes and update dst and len.
  void CopyFromBuffer(char **dst, int32_t *len);

  // Read available data from the socket. Return false on EOF or error.
  bool ReadSomeData();

  static const int kBufSize = 4096;
  nacl::scoped_array<char> buf_;
  int32_t pos_;
  int32_t size_;
  NaClSocketHandle handle_;
#if NACL_WINDOWS
  HANDLE socket_event_;
#endif
};

void Transport::CopyFromBuffer(char **dst, int32_t *len) {
  int32_t copy_bytes = std::min(*len, size_ - pos_);
  memcpy(*dst, buf_.get() + pos_, copy_bytes);
  pos_ += copy_bytes;
  *len -= copy_bytes;
  *dst += copy_bytes;
}

bool Transport::ReadSomeData() {
  while (true) {
    int result = ::recv(handle_, buf_.get() + size_, kBufSize - size_, 0);
    if (result > 0) {
      size_ += result;
      return true;
    }
    if (result == 0)
      return false;
#if NACL_WINDOWS
    // WSAEventSelect sets socket to non-blocking mode. This is essential
    // for socket event notification to work, there is no workaround.
    // See remarks section at the page
    // http://msdn.microsoft.com/en-us/library/windows/desktop/ms741576(v=vs.85).aspx
    if (NaClSocketGetLastError() == WSAEWOULDBLOCK) {
      if (WaitForSingleObject(socket_event_, INFINITE) == WAIT_FAILED) {
        NaClLog(LOG_FATAL,
                "Transport::ReadSomeData: Failed to wait on socket event\n");
      }
      if (!ResetEvent(socket_event_)) {
        NaClLog(LOG_FATAL,
                "Transport::ReadSomeData: Failed to reset socket event\n");
      }
      continue;
    }
#endif
    if (NaClSocketGetLastError() != EINTR)
      return false;
  }
}

bool Transport::Read(void *ptr, int32_t len) {
  char *dst = static_cast<char *>(ptr);
  if (pos_ < size_) {
    CopyFromBuffer(&dst, &len);
  }
  while (len > 0) {
    pos_ = 0;
    size_ = 0;
    if (!ReadSomeData()) {
      return false;
    }
    CopyFromBuffer(&dst, &len);
  }
  return true;
}

bool Transport::Write(const void *ptr, int32_t len) {
  const char *src = static_cast<const char *>(ptr);
  while (len > 0) {
    int result = ::send(handle_, src, len, 0);
    if (result > 0) {
      src += result;
      len -= result;
      continue;
    }
    if (result == 0) {
      return false;
    }
    if (NaClSocketGetLastError() != EINTR) {
      return false;
    }
  }
  return true;
}

void Transport::WaitForDebugStubEvent(struct NaClApp *nap,
                                      bool ignore_input_from_gdb) {
  bool wait = true;
  // If we are told to ignore messages from gdb, we will exit from this
  // function only if new data is sent by gdb.
  if ((pos_ < size_ && !ignore_input_from_gdb) ||
      nap->faulted_thread_count > 0) {
    // Clear faulted thread events to save debug stub loop iterations.
    wait = false;
  }
#if NACL_WINDOWS
  HANDLE handles[2];
  handles[0] = nap->faulted_thread_event;
  handles[1] = socket_event_;
  int count = size_ < kBufSize ? 2 : 1;
  int result = WaitForMultipleObjects(count, handles, FALSE,
                                      wait ? INFINITE : 0);
  if (result == WAIT_OBJECT_0 + 1) {
    if (!ResetEvent(socket_event_)) {
      NaClLog(LOG_FATAL,
              "Transport::WaitForDebugStubEvent: "
              "Failed to reset socket event\n");
    }
    return;
  }
  if (result == WAIT_TIMEOUT || result == WAIT_OBJECT_0)
    return;
  NaClLog(LOG_FATAL,
          "Transport::WaitForDebugStubEvent: Wait for events failed\n");
#else
  fd_set fds;

  FD_ZERO(&fds);
  FD_SET(nap->faulted_thread_fd_read, &fds);
  int max_fd = nap->faulted_thread_fd_read;
  if (size_ < kBufSize) {
    FD_SET(handle_, &fds);
    max_fd = std::max(max_fd, handle_);
  }

  int ret;
  // We don't need sleep-polling on Linux now, so we set either zero or infinite
  // timeout.
  if (wait) {
    ret = select(max_fd + 1, &fds, NULL, NULL, NULL);
  } else {
    struct timeval timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = 0;
    ret = select(max_fd + 1, &fds, NULL, NULL, &timeout);
  }
  if (ret < 0) {
    NaClLog(LOG_FATAL,
            "Transport::WaitForDebugStubEvent: Failed to wait for "
            "debug stub event\n");
  }

  if (ret > 0) {
    if (FD_ISSET(nap->faulted_thread_fd_read, &fds)) {
      char buf[16];
      if (read(nap->faulted_thread_fd_read, &buf, sizeof(buf)) < 0) {
        NaClLog(LOG_FATAL,
                "Transport::WaitForDebugStubEvent: Failed to read from "
                "debug stub event pipe fd\n");
      }
    }
    if (FD_ISSET(handle_, &fds))
      ReadSomeData();
  }
#endif
}

// Convert string in the form of [addr][:port] where addr is a
// IPv4 address or host name, and port is a 16b tcp/udp port.
// Both portions are optional, and only the portion of the address
// provided is updated.  Values are provided in network order.
static bool StringToIPv4(const std::string &instr, uint32_t *addr,
                         uint16_t *port) {
  // Make a copy so the are unchanged unless we succeed
  uint32_t outaddr = *addr;
  uint16_t outport = *port;

  // Substrings of the full ADDR:PORT
  std::string addrstr;
  std::string portstr;

  // We should either have one or two tokens in the form of:
  //  IP - IP, NUL
  //  IP: -  IP, NUL
  //  :PORT - NUL, PORT
  //  IP:PORT - IP, PORT

  // Search for the port marker
  size_t portoff = instr.find(':');

  // If we found a ":" before the end, get both substrings
  if ((portoff != std::string::npos) && (portoff + 1 < instr.size())) {
    addrstr = instr.substr(0, portoff);
    portstr = instr.substr(portoff + 1, std::string::npos);
  } else {
    // otherwise the entire string is the addr portion.
    addrstr = instr;
    portstr = "";
  }

  // If the address portion was provided, update it
  if (addrstr.size()) {
    // Special case 0.0.0.0 which means any IPv4 interface
    if (addrstr == "0.0.0.0") {
      outaddr = 0;
    } else {
      struct hostent *host = gethostbyname(addrstr.data());

      // Check that we found an IPv4 host
      if ((NULL == host) || (AF_INET != host->h_addrtype)) return false;

      // Make sure the IP list isn't empty.
      if (0 == host->h_addr_list[0]) return false;

      // Use the first address in the array of address pointers.
      uint32_t **addrarray = reinterpret_cast<uint32_t**>(host->h_addr_list);
      outaddr = *addrarray[0];
    }
  }

  // if the port portion was provided, then update it
  if (portstr.size()) {
    int val = atoi(portstr.data());
    if ((val < 0) || (val > 65535)) return false;
    outport = ntohs(static_cast<uint16_t>(val));
  }

  // We haven't failed, so set the values
  *addr = outaddr;
  *port = outport;
  return true;
}

static bool BuildSockAddr(const char *addr, struct sockaddr_in *sockaddr) {
  std::string addrstr = addr;
  uint32_t *pip = reinterpret_cast<uint32_t*>(&sockaddr->sin_addr.s_addr);
  uint16_t *pport = reinterpret_cast<uint16_t*>(&sockaddr->sin_port);

  sockaddr->sin_family = AF_INET;
  return StringToIPv4(addrstr, pip, pport);
}

SocketBinding::SocketBinding(NaClSocketHandle socket_handle)
    : socket_handle_(socket_handle) {
}

SocketBinding *SocketBinding::Bind(const char *addr) {
  NaClSocketHandle socket_handle = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (socket_handle == NACL_INVALID_SOCKET) {
    NaClLog(LOG_ERROR, "Failed to create socket.\n");
    return NULL;
  }
  struct sockaddr_in saddr;
  // Clearing sockaddr_in first appears to be necessary on Mac OS X.
  memset(&saddr, 0, sizeof(saddr));
  socklen_t addrlen = static_cast<socklen_t>(sizeof(saddr));
  saddr.sin_family = AF_INET;
  saddr.sin_addr.s_addr = htonl(0x7F000001);
  saddr.sin_port = htons(4014);

  // Override portions address that are provided
  if (addr) BuildSockAddr(addr, &saddr);

  // This is necessary to ensure that the TCP port is released
  // promptly when sel_ldr exits.  Without this, the TCP port might
  // only be released after a timeout, and later processes can fail
  // to bind it.
  int reuse_address = 1;
  if (setsockopt(socket_handle, SOL_SOCKET, SO_REUSEADDR,
                 reinterpret_cast<char *>(&reuse_address),
                 sizeof(reuse_address))) {
    NaClLog(LOG_WARNING, "Failed to set SO_REUSEADDR option.\n");
  }
  // Do not delay sending small packets.  This significantly speeds up
  // remote debugging.  Debug stub uses buffering to send outgoing packets so
  // they are not split into more TCP packets than necessary.
  int nodelay = 1;
  if (setsockopt(socket_handle, IPPROTO_TCP, TCP_NODELAY,
                 reinterpret_cast<char *>(&nodelay),
                 sizeof(nodelay))) {
    NaClLog(LOG_WARNING, "Failed to set TCP_NODELAY option.\n");
  }

  struct sockaddr *psaddr = reinterpret_cast<struct sockaddr *>(&saddr);
  if (bind(socket_handle, psaddr, addrlen)) {
    NaClLog(LOG_ERROR, "Failed to bind server.\n");
    return NULL;
  }

  if (listen(socket_handle, 1)) {
    NaClLog(LOG_ERROR, "Failed to listen.\n");
    return NULL;
  }
  return new SocketBinding(socket_handle);
}

ITransport *SocketBinding::AcceptConnection() {
  NaClSocketHandle socket = ::accept(socket_handle_, NULL, 0);
  if (socket != NACL_INVALID_SOCKET)
    return new Transport(socket);
  return NULL;
}

}  // namespace port
<commit_msg>Debug stub: Set NODELAY on NaCl debug TCP socket<commit_after>/*
 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <errno.h>
#include <stdlib.h>
#include <string.h>

#include <algorithm>
#include <string>

#include "native_client/src/include/nacl_scoped_ptr.h"
#include "native_client/src/include/portability_sockets.h"
#include "native_client/src/shared/platform/nacl_log.h"
#include "native_client/src/trusted/debug_stub/platform.h"
#include "native_client/src/trusted/debug_stub/transport.h"
#include "native_client/src/trusted/debug_stub/util.h"
#include "native_client/src/trusted/service_runtime/sel_ldr.h"

using gdb_rsp::stringvec;
using gdb_rsp::StringSplit;

namespace port {

typedef int socklen_t;

class Transport : public ITransport {
 public:
  Transport()
    : buf_(new char[kBufSize]),
      pos_(0),
      size_(0) {
    handle_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
#if NACL_WINDOWS
    CreateSocketEvent();
#endif
  }

  explicit Transport(NaClSocketHandle s)
    : buf_(new char[kBufSize]),
      pos_(0),
      size_(0),
      handle_(s) {
#if NACL_WINDOWS
    CreateSocketEvent();
#endif
  }

  ~Transport() {
    if (handle_ != NACL_INVALID_SOCKET) NaClCloseSocket(handle_);
#if NACL_WINDOWS
    if (!WSACloseEvent(socket_event_)) {
      NaClLog(LOG_FATAL,
              "Transport::~Transport: Failed to close socket event\n");
    }
#endif
  }

#if NACL_WINDOWS
  void CreateSocketEvent() {
    socket_event_ = WSACreateEvent();
    if (socket_event_ == WSA_INVALID_EVENT) {
      NaClLog(LOG_FATAL,
              "Transport::CreateSocketEvent: Failed to create socket event\n");
    }
    if (WSAEventSelect(handle_, socket_event_, FD_READ) == SOCKET_ERROR) {
      NaClLog(LOG_FATAL,
              "Transport::CreateSocketEvent: Failed to bind event to socket\n");
    }
  }
#endif

  // Read from this transport, return true on success.
  virtual bool Read(void *ptr, int32_t len);

  // Write to this transport, return true on success.
  virtual bool Write(const void *ptr, int32_t len);

  // Return true if there is data to read.
  virtual bool IsDataAvailable() {
    if (pos_ < size_) {
      return true;
    }
    fd_set fds;

    FD_ZERO(&fds);
    FD_SET(handle_, &fds);

    // We want a "non-blocking" check
    struct timeval timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = 0;

    // Check if this file handle can select on read
    int cnt = select(static_cast<int>(handle_) + 1, &fds, 0, 0, &timeout);

    // If we are ready, or if there is an error.  We return true
    // on error, to let the next IO request fail.
    if (cnt != 0) return true;

    return false;
  }

  virtual void WaitForDebugStubEvent(struct NaClApp *nap,
                                     bool ignore_input_from_gdb);

// On windows, the header that defines this has other definition
// colitions, so we define it outselves just in case
#ifndef SD_BOTH
#define SD_BOTH 2
#endif

  virtual void Disconnect() {
    // Shutdown the conneciton in both diections.  This should
    // always succeed, and nothing we can do if this fails.
    (void) ::shutdown(handle_, SD_BOTH);
  }

 protected:
  // Copy buffered data to *dst up to len bytes and update dst and len.
  void CopyFromBuffer(char **dst, int32_t *len);

  // Read available data from the socket. Return false on EOF or error.
  bool ReadSomeData();

  static const int kBufSize = 4096;
  nacl::scoped_array<char> buf_;
  int32_t pos_;
  int32_t size_;
  NaClSocketHandle handle_;
#if NACL_WINDOWS
  HANDLE socket_event_;
#endif
};

void Transport::CopyFromBuffer(char **dst, int32_t *len) {
  int32_t copy_bytes = std::min(*len, size_ - pos_);
  memcpy(*dst, buf_.get() + pos_, copy_bytes);
  pos_ += copy_bytes;
  *len -= copy_bytes;
  *dst += copy_bytes;
}

bool Transport::ReadSomeData() {
  while (true) {
    int result = ::recv(handle_, buf_.get() + size_, kBufSize - size_, 0);
    if (result > 0) {
      size_ += result;
      return true;
    }
    if (result == 0)
      return false;
#if NACL_WINDOWS
    // WSAEventSelect sets socket to non-blocking mode. This is essential
    // for socket event notification to work, there is no workaround.
    // See remarks section at the page
    // http://msdn.microsoft.com/en-us/library/windows/desktop/ms741576(v=vs.85).aspx
    if (NaClSocketGetLastError() == WSAEWOULDBLOCK) {
      if (WaitForSingleObject(socket_event_, INFINITE) == WAIT_FAILED) {
        NaClLog(LOG_FATAL,
                "Transport::ReadSomeData: Failed to wait on socket event\n");
      }
      if (!ResetEvent(socket_event_)) {
        NaClLog(LOG_FATAL,
                "Transport::ReadSomeData: Failed to reset socket event\n");
      }
      continue;
    }
#endif
    if (NaClSocketGetLastError() != EINTR)
      return false;
  }
}

bool Transport::Read(void *ptr, int32_t len) {
  char *dst = static_cast<char *>(ptr);
  if (pos_ < size_) {
    CopyFromBuffer(&dst, &len);
  }
  while (len > 0) {
    pos_ = 0;
    size_ = 0;
    if (!ReadSomeData()) {
      return false;
    }
    CopyFromBuffer(&dst, &len);
  }
  return true;
}

bool Transport::Write(const void *ptr, int32_t len) {
  const char *src = static_cast<const char *>(ptr);
  while (len > 0) {
    int result = ::send(handle_, src, len, 0);
    if (result > 0) {
      src += result;
      len -= result;
      continue;
    }
    if (result == 0) {
      return false;
    }
    if (NaClSocketGetLastError() != EINTR) {
      return false;
    }
  }
  return true;
}

void Transport::WaitForDebugStubEvent(struct NaClApp *nap,
                                      bool ignore_input_from_gdb) {
  bool wait = true;
  // If we are told to ignore messages from gdb, we will exit from this
  // function only if new data is sent by gdb.
  if ((pos_ < size_ && !ignore_input_from_gdb) ||
      nap->faulted_thread_count > 0) {
    // Clear faulted thread events to save debug stub loop iterations.
    wait = false;
  }
#if NACL_WINDOWS
  HANDLE handles[2];
  handles[0] = nap->faulted_thread_event;
  handles[1] = socket_event_;
  int count = size_ < kBufSize ? 2 : 1;
  int result = WaitForMultipleObjects(count, handles, FALSE,
                                      wait ? INFINITE : 0);
  if (result == WAIT_OBJECT_0 + 1) {
    if (!ResetEvent(socket_event_)) {
      NaClLog(LOG_FATAL,
              "Transport::WaitForDebugStubEvent: "
              "Failed to reset socket event\n");
    }
    return;
  }
  if (result == WAIT_TIMEOUT || result == WAIT_OBJECT_0)
    return;
  NaClLog(LOG_FATAL,
          "Transport::WaitForDebugStubEvent: Wait for events failed\n");
#else
  fd_set fds;

  FD_ZERO(&fds);
  FD_SET(nap->faulted_thread_fd_read, &fds);
  int max_fd = nap->faulted_thread_fd_read;
  if (size_ < kBufSize) {
    FD_SET(handle_, &fds);
    max_fd = std::max(max_fd, handle_);
  }

  int ret;
  // We don't need sleep-polling on Linux now, so we set either zero or infinite
  // timeout.
  if (wait) {
    ret = select(max_fd + 1, &fds, NULL, NULL, NULL);
  } else {
    struct timeval timeout;
    timeout.tv_sec = 0;
    timeout.tv_usec = 0;
    ret = select(max_fd + 1, &fds, NULL, NULL, &timeout);
  }
  if (ret < 0) {
    NaClLog(LOG_FATAL,
            "Transport::WaitForDebugStubEvent: Failed to wait for "
            "debug stub event\n");
  }

  if (ret > 0) {
    if (FD_ISSET(nap->faulted_thread_fd_read, &fds)) {
      char buf[16];
      if (read(nap->faulted_thread_fd_read, &buf, sizeof(buf)) < 0) {
        NaClLog(LOG_FATAL,
                "Transport::WaitForDebugStubEvent: Failed to read from "
                "debug stub event pipe fd\n");
      }
    }
    if (FD_ISSET(handle_, &fds))
      ReadSomeData();
  }
#endif
}

// Convert string in the form of [addr][:port] where addr is a
// IPv4 address or host name, and port is a 16b tcp/udp port.
// Both portions are optional, and only the portion of the address
// provided is updated.  Values are provided in network order.
static bool StringToIPv4(const std::string &instr, uint32_t *addr,
                         uint16_t *port) {
  // Make a copy so the are unchanged unless we succeed
  uint32_t outaddr = *addr;
  uint16_t outport = *port;

  // Substrings of the full ADDR:PORT
  std::string addrstr;
  std::string portstr;

  // We should either have one or two tokens in the form of:
  //  IP - IP, NUL
  //  IP: -  IP, NUL
  //  :PORT - NUL, PORT
  //  IP:PORT - IP, PORT

  // Search for the port marker
  size_t portoff = instr.find(':');

  // If we found a ":" before the end, get both substrings
  if ((portoff != std::string::npos) && (portoff + 1 < instr.size())) {
    addrstr = instr.substr(0, portoff);
    portstr = instr.substr(portoff + 1, std::string::npos);
  } else {
    // otherwise the entire string is the addr portion.
    addrstr = instr;
    portstr = "";
  }

  // If the address portion was provided, update it
  if (addrstr.size()) {
    // Special case 0.0.0.0 which means any IPv4 interface
    if (addrstr == "0.0.0.0") {
      outaddr = 0;
    } else {
      struct hostent *host = gethostbyname(addrstr.data());

      // Check that we found an IPv4 host
      if ((NULL == host) || (AF_INET != host->h_addrtype)) return false;

      // Make sure the IP list isn't empty.
      if (0 == host->h_addr_list[0]) return false;

      // Use the first address in the array of address pointers.
      uint32_t **addrarray = reinterpret_cast<uint32_t**>(host->h_addr_list);
      outaddr = *addrarray[0];
    }
  }

  // if the port portion was provided, then update it
  if (portstr.size()) {
    int val = atoi(portstr.data());
    if ((val < 0) || (val > 65535)) return false;
    outport = ntohs(static_cast<uint16_t>(val));
  }

  // We haven't failed, so set the values
  *addr = outaddr;
  *port = outport;
  return true;
}

static bool BuildSockAddr(const char *addr, struct sockaddr_in *sockaddr) {
  std::string addrstr = addr;
  uint32_t *pip = reinterpret_cast<uint32_t*>(&sockaddr->sin_addr.s_addr);
  uint16_t *pport = reinterpret_cast<uint16_t*>(&sockaddr->sin_port);

  sockaddr->sin_family = AF_INET;
  return StringToIPv4(addrstr, pip, pport);
}

SocketBinding::SocketBinding(NaClSocketHandle socket_handle)
    : socket_handle_(socket_handle) {
}

SocketBinding *SocketBinding::Bind(const char *addr) {
  NaClSocketHandle socket_handle = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (socket_handle == NACL_INVALID_SOCKET) {
    NaClLog(LOG_ERROR, "Failed to create socket.\n");
    return NULL;
  }
  struct sockaddr_in saddr;
  // Clearing sockaddr_in first appears to be necessary on Mac OS X.
  memset(&saddr, 0, sizeof(saddr));
  socklen_t addrlen = static_cast<socklen_t>(sizeof(saddr));
  saddr.sin_family = AF_INET;
  saddr.sin_addr.s_addr = htonl(0x7F000001);
  saddr.sin_port = htons(4014);

  // Override portions address that are provided
  if (addr) BuildSockAddr(addr, &saddr);

  // This is necessary to ensure that the TCP port is released
  // promptly when sel_ldr exits.  Without this, the TCP port might
  // only be released after a timeout, and later processes can fail
  // to bind it.
  int reuse_address = 1;
  if (setsockopt(socket_handle, SOL_SOCKET, SO_REUSEADDR,
                 reinterpret_cast<char *>(&reuse_address),
                 sizeof(reuse_address))) {
    NaClLog(LOG_WARNING, "Failed to set SO_REUSEADDR option.\n");
  }

  struct sockaddr *psaddr = reinterpret_cast<struct sockaddr *>(&saddr);
  if (bind(socket_handle, psaddr, addrlen)) {
    NaClLog(LOG_ERROR, "Failed to bind server.\n");
    return NULL;
  }

  if (listen(socket_handle, 1)) {
    NaClLog(LOG_ERROR, "Failed to listen.\n");
    return NULL;
  }
  return new SocketBinding(socket_handle);
}

ITransport *SocketBinding::AcceptConnection() {
  NaClSocketHandle socket = ::accept(socket_handle_, NULL, 0);
  if (socket != NACL_INVALID_SOCKET) {
    // Do not delay sending small packets.  This significantly speeds up
    // remote debugging.  Debug stub uses buffering to send outgoing packets so
    // they are not split into more TCP packets than necessary.
    int nodelay = 1;
    if (setsockopt(socket, IPPROTO_TCP, TCP_NODELAY,
                   reinterpret_cast<char *>(&nodelay),
                   sizeof(nodelay))) {
      NaClLog(LOG_WARNING, "Failed to set TCP_NODELAY option.\n");
    }
    return new Transport(socket);
  }
  return NULL;
}

}  // namespace port
<|endoftext|>


<commit_before>#include "TestBlockLandApplication.h"
#include <OIS.h>
#include <iostream>

const BlockInfo BLOCKINFO[] = {
	{ BlockType::Air, "Air", Ogre::ColourValue(1.0, 1.0, 1.0) },
	{ BlockType::Grass, "Grass", Ogre::ColourValue(0.0, 0.5, 0.0) },
	{ BlockType::Soil, "Soil", Ogre::ColourValue(0.5, 0.3, 0.0) },
	{ BlockType::Rock, "Rock", Ogre::ColourValue(0.5, 0.5, 0.5) }
};

TestBlockLandApplication::TestBlockLandApplication() :
		_worldXSize(-1), _worldZSize(-1), _chunkID(1), _blocks(nullptr) {
}

TestBlockLandApplication::~TestBlockLandApplication() {
	delete[] _blocks;
}

void TestBlockLandApplication::initWorldBlocksCaves() {
	// Change these to increase/decrease the cave size scale
	const float delta = 0.01f;
	const float valueLimit = 0.80f;

	float nx, ny, nz;
	for (int y = 0, ny = 0.0f; y < _worldHeight; ++y, ny += delta) {
		for (int z = 0, nz = 0.0f; z < _worldZSize; ++z, nz += delta) {
			for (int x = 0, nx = 0.0f; x < _worldXSize; ++x, nx += delta) {
			//	const float value = NoiseSource.GetValue(nx, ny, nz);
			//	if (value > valueLimit)
			//		getBlock(x, y, z).type = BlockType::Air;
			}
		}
	}
}

void TestBlockLandApplication::initWorldBlocksLight() {
	const LightValue deltaLight = 16;

	for (int z = 0; z < _worldZSize; ++z) {
		for (int x = 0; x < _worldXSize; ++x) {
			LightValue light = 255;

			for (int y = _worldHeight - 1; y >= 0; --y) {
				getBlockLight(x, y, z) = light;

				if (getBlock(x, y, z).type != BlockType::Air) {
					if (light >= deltaLight)
						light -= deltaLight;
					else
						light = 0;
				}
			}
		}
	}
}

void TestBlockLandApplication::createChunk(const int startX, const int startY, const int startZ) {
	Ogre::ManualObject* meshChunk = new Ogre::ManualObject("MeshMatChunk" + Ogre::StringConverter::toString(_chunkID));
	meshChunk->begin("BaseWhiteNoLighting");
	/* Only create visible faces of chunk */
	const BlockType defaultBlock = BlockType::Grass;
	const int sx = 0;
	const int sy = 0;
	const int sz = 0;

	int vertexIndex = 0;

	for (int z = startZ; z < CHUNK_SIZE + startZ; ++z) {
		for (int y = startY; y < CHUNK_SIZE + startY; ++y) {
			for (int x = startX; x < CHUNK_SIZE + startX; ++x) {
				const BlockType type = getBlock(x, y, z).type;
				if (type == BlockType::Air)
					continue;

				const float blockLightX = getBlockLight(x, y, z) / 255.0f;
				const float blockLightZ = blockLightX * 0.9f;
				const float blockLightY = blockLightX * 0.8f;

				BlockType blockType = defaultBlock;
				if (x > sx)
					blockType = getBlock(x - 1, y, z).type;

				const Ogre::ColourValue& color = BLOCKINFO[static_cast<int>(type)].color;
				if (blockType == BlockType::Air) {
					const Ogre::Vector3 normal(-1, 0, 0);
					mesh(meshChunk, normal, color * blockLightX, vertexIndex, x, y, z + 1, x, y + 1, z + 1, x, y + 1, z, x, y, z);
				}

				blockType = defaultBlock;
				if (x < sx + _worldXSize - 1)
					blockType = getBlock(x + 1, y, z).type;

				if (blockType == BlockType::Air) {
					const Ogre::Vector3 normal(1, 0, 0);
					mesh(meshChunk, normal, color * blockLightX, vertexIndex, x + 1, y, z, x + 1, y + 1, z, x + 1, y + 1, z + 1, x + 1, y, z + 1);
				}

				blockType = defaultBlock;
				if (y > sy)
					blockType = getBlock(x, y - 1, z).type;

				if (blockType == BlockType::Air) {
					const Ogre::Vector3 normal(0, -1, 0);
					mesh(meshChunk, normal, color * blockLightY, vertexIndex, x, y, z, x + 1, y, z, x + 1, y, z + 1, x, y, z + 1);
				}

				blockType = defaultBlock;
				if (y < sy + _worldHeight - 1)
					blockType = getBlock(x, y + 1, z).type;

				if (blockType == BlockType::Air) {
					const Ogre::Vector3 normal(0, 1, 0);
					mesh(meshChunk, normal, color * blockLightY, vertexIndex, x, y + 1, z + 1, x + 1, y + 1, z + 1, x + 1, y + 1, z, x, y + 1, z);
				}

				blockType = defaultBlock;
				if (z > sz)
					blockType = getBlock(x, y, z - 1).type;

				if (blockType == BlockType::Air) {
					const Ogre::Vector3 normal(0, 0, -1);
					mesh(meshChunk, normal, color * blockLightZ, vertexIndex, x, y + 1, z, x + 1, y + 1, z, x + 1, y, z, x, y, z);
				}

				blockType = defaultBlock;
				if (z < sz + _worldZSize - 1)
					blockType = getBlock(x, y, z + 1).type;

				if (blockType == BlockType::Air) {
					const Ogre::Vector3 normal(0, 0, 1);
					mesh(meshChunk, normal, color * blockLightZ, vertexIndex, x, y, z + 1, x + 1, y, z + 1, x + 1, y + 1, z + 1, x, y + 1, z + 1);
				}
			}
		}
	}
	meshChunk->end();

	mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(meshChunk);

	++_chunkID;
}

Ogre::MaterialPtr TestBlockLandApplication::createSolidTexture(const Ogre::String& pName, const Ogre::ColourValue& color) {
	Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create(pName, "General");
	Ogre::Technique* tech = mat->getTechnique(0);
	tech->setLightingEnabled(true);
	Ogre::Pass* pass = tech->getPass(0);
	Ogre::TextureUnitState* tex = pass->createTextureUnitState();
	tex->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, color);
	return mat;
}

void TestBlockLandApplication::createWorldChunks() {
	for (int z = 0; z < _worldZSize; z += CHUNK_SIZE) {
		for (int y = 0; y < _worldHeight; y += CHUNK_SIZE) {
			for (int x = 0; x < _worldXSize; x += CHUNK_SIZE) {
				createChunk(x, y, z);
			}
		}
	}
}

void TestBlockLandApplication::createScene() {
	mSceneMgr->setSkyDome(true, "Examples/CloudySky", 2, 8, 100);
	mSceneMgr->setFog(Ogre::FOG_LINEAR, Ogre::ColourValue(0.8, 0.8, 1), 0.05, 0.0, 200);

	mCamera->setFarClipDistance(256);
	mCamera->setNearClipDistance(0.01);

	mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5));
	Ogre::Light* l = mSceneMgr->createLight("MainLight");
	l->setPosition(20, 80, 50);

	initWorldBlocksTerrain();
	Ogre::LogManager::getSingletonPtr()->logMessage("*** initWorldBlocksCaves ***");
	//initWorldBlocksCaves();
	Ogre::LogManager::getSingletonPtr()->logMessage("*** initWorldBlocksLight ***");
	initWorldBlocksLight();

	Ogre::LogManager::getSingletonPtr()->logMessage("*** createWorldChunks ***");
	createWorldChunks();

	Ogre::LogManager::getSingletonPtr()->logMessage("*** done ***");
}

TArray2D<TVec4D<float>> TestBlockLandApplication::createHeightMapImage() {
	CMWC4096 rnd;
	rnd.setSeedTime();
	CImplicitFractal frac1(anl::EFractalTypes::FBM, anl::GRADIENT, anl::QUINTIC);

	frac1.setSeed(rnd.get());

	CImplicitAutoCorrect ac1(0.0, 1.0);

	ac1.setSource(&frac1);

	CRGBACompositeChannels compose1(anl::RGB);

	compose1.setRedSource(&ac1);
	compose1.setGreenSource(&ac1);
	compose1.setBlueSource(&ac1);
	compose1.setAlphaSource(1.0);

	TArray2D<TVec4D<float>> img(256, 256);

	SMappingRanges ranges;
	mapRGBA2D(anl::SEAMLESS_NONE, img ,compose1 ,ranges, 0);

	//Just for debugging purpose
	saveRGBAArray((char*)"heightmap.tga", &img);

	return img;
}

void TestBlockLandApplication::initWorldBlocksTerrain() {
	Ogre::LogManager::getSingletonPtr()->logMessage("*** initWorldBlocksTerrain: create textures ***");
	const int length = lengthof(BLOCKINFO);
	for (int i = 1; i < length; ++i) {
		const BlockInfo& info = BLOCKINFO[i];
		createSolidTexture(info.name, info.color);
	}

	TArray2D<TVec4D<float>> map = createHeightMapImage();

	_worldXSize = map.width();
	_worldZSize = map.height();

	std::ostringstream ss;
	ss << "*** initWorldBlocksTerrain: size " << _worldXSize << ":" << _worldZSize << "***";

	_blocks = new Block[_worldZSize * _worldXSize * _worldHeight];
	memset(_blocks, 0, sizeof(Block) * _worldZSize * _worldXSize * _worldHeight);

	Ogre::LogManager::getSingletonPtr()->logMessage(ss.str().c_str());

	for (int z = 0; z < _worldZSize; ++z) {
		for (int x = 0; x < _worldXSize; ++x) {
			//TODO: scale into world height
			TVec4D<float> color = map.get(x, z);
			const int height = static_cast<int>(((color.get_x() + color.get_y() + color.get_z()) / 3.0f) * 255.0f);
			for (int y = 0; y < height; ++y) {
				assert(height < _worldHeight);
				getBlock(x, y, z).type = getLayerType(height);
			}
		}
	}
}

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT)
#else
int main(int argc, char *argv[])
#endif
		{
	// Create application object
	TestBlockLandApplication app;

	try {
		app.go();
	} catch (Ogre::Exception& e) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
		MessageBox(NULL, e.getFullDescription().c_str(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
		std::cerr << "An exception has occurred: " << e.getFullDescription().c_str() << std::endl;
#endif
	}

	return 0;
}

#ifdef __cplusplus
}
#endif
<commit_msg>* changed the noise to generate a plain-like landscape<commit_after>#include "TestBlockLandApplication.h"
#include <OIS.h>
#include <iostream>

const BlockInfo BLOCKINFO[] = {
	{ BlockType::Air, "Air", Ogre::ColourValue(1.0, 1.0, 1.0) },
	{ BlockType::Grass, "Grass", Ogre::ColourValue(0.0, 0.5, 0.0) },
	{ BlockType::Soil, "Soil", Ogre::ColourValue(0.5, 0.3, 0.0) },
	{ BlockType::Rock, "Rock", Ogre::ColourValue(0.5, 0.5, 0.5) }
};

TestBlockLandApplication::TestBlockLandApplication() :
		_worldXSize(-1), _worldZSize(-1), _chunkID(1), _blocks(nullptr) {
}

TestBlockLandApplication::~TestBlockLandApplication() {
	delete[] _blocks;
}

void TestBlockLandApplication::initWorldBlocksCaves() {
	// Change these to increase/decrease the cave size scale
	const float delta = 0.01f;
	const float valueLimit = 0.80f;

	float nx, ny, nz;
	for (int y = 0, ny = 0.0f; y < _worldHeight; ++y, ny += delta) {
		for (int z = 0, nz = 0.0f; z < _worldZSize; ++z, nz += delta) {
			for (int x = 0, nx = 0.0f; x < _worldXSize; ++x, nx += delta) {
			//	const float value = NoiseSource.GetValue(nx, ny, nz);
			//	if (value > valueLimit)
			//		getBlock(x, y, z).type = BlockType::Air;
			}
		}
	}
}

void TestBlockLandApplication::initWorldBlocksLight() {
	const LightValue deltaLight = 16;

	for (int z = 0; z < _worldZSize; ++z) {
		for (int x = 0; x < _worldXSize; ++x) {
			LightValue light = 255;

			for (int y = _worldHeight - 1; y >= 0; --y) {
				getBlockLight(x, y, z) = light;

				if (getBlock(x, y, z).type != BlockType::Air) {
					if (light >= deltaLight)
						light -= deltaLight;
					else
						light = 0;
				}
			}
		}
	}
}

void TestBlockLandApplication::createChunk(const int startX, const int startY, const int startZ) {
	Ogre::ManualObject* meshChunk = new Ogre::ManualObject("MeshMatChunk" + Ogre::StringConverter::toString(_chunkID));
	meshChunk->begin("BaseWhiteNoLighting");
	/* Only create visible faces of chunk */
	const BlockType defaultBlock = BlockType::Grass;
	const int sx = 0;
	const int sy = 0;
	const int sz = 0;

	int vertexIndex = 0;

	for (int z = startZ; z < CHUNK_SIZE + startZ; ++z) {
		for (int y = startY; y < CHUNK_SIZE + startY; ++y) {
			for (int x = startX; x < CHUNK_SIZE + startX; ++x) {
				const BlockType type = getBlock(x, y, z).type;
				if (type == BlockType::Air)
					continue;

				const float blockLightX = getBlockLight(x, y, z) / 255.0f;
				const float blockLightZ = blockLightX * 0.9f;
				const float blockLightY = blockLightX * 0.8f;

				BlockType blockType = defaultBlock;
				if (x > sx)
					blockType = getBlock(x - 1, y, z).type;

				const Ogre::ColourValue& color = BLOCKINFO[static_cast<int>(type)].color;
				if (blockType == BlockType::Air) {
					const Ogre::Vector3 normal(-1, 0, 0);
					mesh(meshChunk, normal, color * blockLightX, vertexIndex, x, y, z + 1, x, y + 1, z + 1, x, y + 1, z, x, y, z);
				}

				blockType = defaultBlock;
				if (x < sx + _worldXSize - 1)
					blockType = getBlock(x + 1, y, z).type;

				if (blockType == BlockType::Air) {
					const Ogre::Vector3 normal(1, 0, 0);
					mesh(meshChunk, normal, color * blockLightX, vertexIndex, x + 1, y, z, x + 1, y + 1, z, x + 1, y + 1, z + 1, x + 1, y, z + 1);
				}

				blockType = defaultBlock;
				if (y > sy)
					blockType = getBlock(x, y - 1, z).type;

				if (blockType == BlockType::Air) {
					const Ogre::Vector3 normal(0, -1, 0);
					mesh(meshChunk, normal, color * blockLightY, vertexIndex, x, y, z, x + 1, y, z, x + 1, y, z + 1, x, y, z + 1);
				}

				blockType = defaultBlock;
				if (y < sy + _worldHeight - 1)
					blockType = getBlock(x, y + 1, z).type;

				if (blockType == BlockType::Air) {
					const Ogre::Vector3 normal(0, 1, 0);
					mesh(meshChunk, normal, color * blockLightY, vertexIndex, x, y + 1, z + 1, x + 1, y + 1, z + 1, x + 1, y + 1, z, x, y + 1, z);
				}

				blockType = defaultBlock;
				if (z > sz)
					blockType = getBlock(x, y, z - 1).type;

				if (blockType == BlockType::Air) {
					const Ogre::Vector3 normal(0, 0, -1);
					mesh(meshChunk, normal, color * blockLightZ, vertexIndex, x, y + 1, z, x + 1, y + 1, z, x + 1, y, z, x, y, z);
				}

				blockType = defaultBlock;
				if (z < sz + _worldZSize - 1)
					blockType = getBlock(x, y, z + 1).type;

				if (blockType == BlockType::Air) {
					const Ogre::Vector3 normal(0, 0, 1);
					mesh(meshChunk, normal, color * blockLightZ, vertexIndex, x, y, z + 1, x + 1, y, z + 1, x + 1, y + 1, z + 1, x, y + 1, z + 1);
				}
			}
		}
	}
	meshChunk->end();

	mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(meshChunk);

	++_chunkID;
}

Ogre::MaterialPtr TestBlockLandApplication::createSolidTexture(const Ogre::String& pName, const Ogre::ColourValue& color) {
	Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create(pName, "General");
	Ogre::Technique* tech = mat->getTechnique(0);
	tech->setLightingEnabled(true);
	Ogre::Pass* pass = tech->getPass(0);
	Ogre::TextureUnitState* tex = pass->createTextureUnitState();
	tex->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, color);
	return mat;
}

void TestBlockLandApplication::createWorldChunks() {
	for (int z = 0; z < _worldZSize; z += CHUNK_SIZE) {
		for (int y = 0; y < _worldHeight; y += CHUNK_SIZE) {
			for (int x = 0; x < _worldXSize; x += CHUNK_SIZE) {
				createChunk(x, y, z);
			}
		}
	}
}

void TestBlockLandApplication::createScene() {
	mSceneMgr->setSkyDome(true, "Examples/CloudySky", 2, 8, 100);
	mSceneMgr->setFog(Ogre::FOG_LINEAR, Ogre::ColourValue(0.8, 0.8, 1), 0.05, 0.0, 200);

	mCamera->setFarClipDistance(256);
	mCamera->setNearClipDistance(0.01);

	mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5));
	Ogre::Light* l = mSceneMgr->createLight("MainLight");
	l->setPosition(20, 80, 50);

	initWorldBlocksTerrain();
	Ogre::LogManager::getSingletonPtr()->logMessage("*** initWorldBlocksCaves ***");
	//initWorldBlocksCaves();
	Ogre::LogManager::getSingletonPtr()->logMessage("*** initWorldBlocksLight ***");
	initWorldBlocksLight();

	Ogre::LogManager::getSingletonPtr()->logMessage("*** createWorldChunks ***");
	createWorldChunks();

	Ogre::LogManager::getSingletonPtr()->logMessage("*** done ***");
}

TArray2D<TVec4D<float>> TestBlockLandApplication::createHeightMapImage() {
	CMWC4096 rnd;
	rnd.setSeedTime();
	CImplicitFractal fractalPlains(anl::EFractalTypes::FBM, anl::GRADIENT, anl::QUINTIC);
	fractalPlains.setNumOctaves(2);
	fractalPlains.setFrequency(1);
	fractalPlains.setSeed(rnd.get());

	CImplicitAutoCorrect autoCorrectPlains(0.0, 1.0);
	autoCorrectPlains.setSource(&fractalPlains);

	CImplicitScaleOffset scaleOffsetPlains(0.1, 0.0);
	scaleOffsetPlains.setSource(&autoCorrectPlains);

	CRGBACompositeChannels composite(anl::RGB);
	composite.setRedSource(&scaleOffsetPlains);
	composite.setGreenSource(&scaleOffsetPlains);
	composite.setBlueSource(&scaleOffsetPlains);
	composite.setAlphaSource(1.0);

	TArray2D<TVec4D<float>> img(256, 256);

	SMappingRanges ranges;
	mapRGBA2D(anl::SEAMLESS_NONE, img ,composite ,ranges, 0);

	//Just for debugging purpose
	saveRGBAArray((char*)"heightmap.tga", &img);

	return img;
}

void TestBlockLandApplication::initWorldBlocksTerrain() {
	Ogre::LogManager::getSingletonPtr()->logMessage("*** initWorldBlocksTerrain: create textures ***");
	const int length = lengthof(BLOCKINFO);
	for (int i = 1; i < length; ++i) {
		const BlockInfo& info = BLOCKINFO[i];
		createSolidTexture(info.name, info.color);
	}

	TArray2D<TVec4D<float>> map = createHeightMapImage();

	_worldXSize = map.width();
	_worldZSize = map.height();

	std::ostringstream ss;
	ss << "*** initWorldBlocksTerrain: size " << _worldXSize << ":" << _worldZSize << "***";

	_blocks = new Block[_worldZSize * _worldXSize * _worldHeight];
	memset(_blocks, 0, sizeof(Block) * _worldZSize * _worldXSize * _worldHeight);

	Ogre::LogManager::getSingletonPtr()->logMessage(ss.str().c_str());

	for (int z = 0; z < _worldZSize; ++z) {
		for (int x = 0; x < _worldXSize; ++x) {
			//TODO: scale into world height
			TVec4D<float> color = map.get(x, z);
			const int height = static_cast<int>(((color.get_x() + color.get_y() + color.get_z()) / 3.0f) * 255.0f);
			for (int y = 0; y < height; ++y) {
				assert(height < _worldHeight);
				getBlock(x, y, z).type = getLayerType(height);
			}
		}
	}
}

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT)
#else
int main(int argc, char *argv[])
#endif
		{
	// Create application object
	TestBlockLandApplication app;

	try {
		app.go();
	} catch (Ogre::Exception& e) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
		MessageBox(NULL, e.getFullDescription().c_str(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
		std::cerr << "An exception has occurred: " << e.getFullDescription().c_str() << std::endl;
#endif
	}

	return 0;
}

#ifdef __cplusplus
}
#endif
<|endoftext|>


<commit_before>/*
 * This file is a part of Xpiks - cross platform application for
 * keywording and uploading images for microstocks
 * Copyright (C) 2014-2015 Taras Kushnir <kushnirTV@gmail.com>
 *
 * Xpiks is distributed under the GNU General Public License, version 3.0
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "uploadcoordinator.h"
#include <QString>
#include <QRegExp>
#include <QFileInfo>
#include <QThread>
#include <QtMath>
#include "../Models/artworkmetadata.h"
#include "uploaditem.h"
#include "externaltoolsprovider.h"
#include "uploadworker.h"
#include "../Helpers/ziphelper.h"

namespace Helpers {
    void UploadCoordinator::uploadArtworks(const QList<Models::ArtworkMetadata *> &artworkList,
                                           const QList<Models::UploadInfo *> &uploadInfos,
                                           bool includeEPS, const Encryption::SecretsManager *secretsManager)
    {
        QStringList filePathes;
        QStringList zipsPathes;
        extractFilePathes(artworkList, filePathes, zipsPathes, includeEPS);

        QList<UploadItem*> uploadItems;
        const QString &curlPath = Helpers::ExternalToolsProvider::getCurlPath();
        int oneItemUploadTimeout = Helpers::ExternalToolsProvider::getOneItemUploadMinutesTimeout();

        int count = uploadInfos.length();
        for (int i = 0; i < count; ++i) {
            Models::UploadInfo * info = uploadInfos.at(i);
            if (info->getIsSelected()) {
                UploadItem *item;
                bool useZips = info->getZipBeforeUpload();
                item = new UploadItem(info, i, useZips ? zipsPathes : filePathes, oneItemUploadTimeout, curlPath);
                uploadItems.append(item);
            }
        }

        emit uploadStarted();

        m_AnyFailed = false;
        m_WorkersCount = 0;
        m_AllWorkersCount = uploadItems.count();
        m_PercentDone = 0;

        if (m_AllWorkersCount > 0) {
            doRunUpload(uploadItems, secretsManager);
        } else {
            emit uploadFinished(true);
        }
    }

    void UploadCoordinator::cancelUpload()
    {
        emit cancelAll();
    }

    void UploadCoordinator::workerFinished(int index, bool success)
    {
        bool allWorkersFinished = false;

        m_Mutex.lock();
        {
            m_AnyFailed = m_AnyFailed || !success;
            m_WorkersCount++;
            allWorkersFinished = m_WorkersCount == m_AllWorkersCount;
        }
        m_Mutex.unlock();

        emit itemFinished(success);

        if (allWorkersFinished) {
            Q_ASSERT(m_UploadSemaphore.available() == MAX_PARALLEL_UPLOAD);
            emit percentChanged(100);
            emit percentChangedForItem(index, 100);
            m_PercentDone = 100;
            emit uploadFinished(!m_AnyFailed);
            stopThreads();
        }
    }

    void UploadCoordinator::percentReported(int index, double newPercent, double oldPercent)
    {
        double n = m_UploadThreads.length();
        if (n == 0) { n = 1.0; }
        int percentDone = 0;

        m_PercentMutex.lock();
        {
            m_PercentDone -= oldPercent/n;
            m_PercentDone += newPercent/n;
            percentDone = m_PercentDone;
        }
        m_PercentMutex.unlock();

        emit percentChanged(percentDone);
        emit percentChangedForItem(index, (int)qFloor(newPercent));
    }

    void UploadCoordinator::doRunUpload(const QList<UploadItem*> &uploadItems,
                                        const Encryption::SecretsManager *secretsManager)
    {
        int i = 0;
        foreach (UploadItem *uploadItem, uploadItems) {
            UploadWorker *worker = new UploadWorker(uploadItem, secretsManager, &m_UploadSemaphore, i);
            QThread *thread = new QThread();
            worker->moveToThread(thread);

            QObject::connect(thread, SIGNAL(started()), worker, SLOT(process()));
            QObject::connect(worker, SIGNAL(stopped()), thread, SLOT(quit()));

            QObject::connect(worker, SIGNAL(stopped()), worker, SLOT(deleteLater()));
            QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

            QObject::connect(worker, SIGNAL(finished(int,bool)), this, SLOT(workerFinished(int,bool)));
            QObject::connect(this, SIGNAL(cancelAll()), worker, SLOT(cancel()));

            QObject::connect(worker, SIGNAL(percentChanged(int, double,double)),
                             this, SLOT(percentReported(int, double,double)));

            m_UploadThreads.append(thread);

            thread->start();
            i++;
        }
    }

    void UploadCoordinator::extractFilePathes(const QList<Models::ArtworkMetadata *> &artworkList,
                                              QStringList &filePathes,
                                              QStringList &zipsPathes,
                                              bool includeEPS) const {

        foreach(Models::ArtworkMetadata *metadata, artworkList) {
            QString filepath = metadata->getFilepath();
            filePathes.append(filepath);

            if (includeEPS) {
                QString epsFilepath = filepath.replace(QRegExp("(.*)[.]jpg", Qt::CaseInsensitive), "\\1.eps");
                if (QFileInfo(epsFilepath).exists()) {
                    filePathes.append(epsFilepath);
                }
            }

            QString zipPath = Helpers::getArchivePath(filepath);
            zipsPathes.append(zipPath);
        }
    }

    void UploadCoordinator::stopThreads()
    {
        // threads are stopped on worker stopped signal
        // and deleted with thread finished signal binding
        m_UploadThreads.clear();
    }
}

<commit_msg>Added ability to upload .ai as well as .eps<commit_after>/*
 * This file is a part of Xpiks - cross platform application for
 * keywording and uploading images for microstocks
 * Copyright (C) 2014-2015 Taras Kushnir <kushnirTV@gmail.com>
 *
 * Xpiks is distributed under the GNU General Public License, version 3.0
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "uploadcoordinator.h"
#include <QString>
#include <QRegExp>
#include <QFileInfo>
#include <QThread>
#include <QtMath>
#include "../Models/artworkmetadata.h"
#include "uploaditem.h"
#include "externaltoolsprovider.h"
#include "uploadworker.h"
#include "../Helpers/ziphelper.h"

namespace Helpers {
    void UploadCoordinator::uploadArtworks(const QList<Models::ArtworkMetadata *> &artworkList,
                                           const QList<Models::UploadInfo *> &uploadInfos,
                                           bool includeEPS, const Encryption::SecretsManager *secretsManager)
    {
        QStringList filePathes;
        QStringList zipsPathes;
        extractFilePathes(artworkList, filePathes, zipsPathes, includeEPS);

        QList<UploadItem*> uploadItems;
        const QString &curlPath = Helpers::ExternalToolsProvider::getCurlPath();
        int oneItemUploadTimeout = Helpers::ExternalToolsProvider::getOneItemUploadMinutesTimeout();

        int count = uploadInfos.length();
        for (int i = 0; i < count; ++i) {
            Models::UploadInfo * info = uploadInfos.at(i);
            if (info->getIsSelected()) {
                UploadItem *item;
                bool useZips = info->getZipBeforeUpload();
                item = new UploadItem(info, i, useZips ? zipsPathes : filePathes, oneItemUploadTimeout, curlPath);
                uploadItems.append(item);
            }
        }

        emit uploadStarted();

        m_AnyFailed = false;
        m_WorkersCount = 0;
        m_AllWorkersCount = uploadItems.count();
        m_PercentDone = 0;

        if (m_AllWorkersCount > 0) {
            doRunUpload(uploadItems, secretsManager);
        } else {
            emit uploadFinished(true);
        }
    }

    void UploadCoordinator::cancelUpload()
    {
        emit cancelAll();
    }

    void UploadCoordinator::workerFinished(int index, bool success)
    {
        bool allWorkersFinished = false;

        m_Mutex.lock();
        {
            m_AnyFailed = m_AnyFailed || !success;
            m_WorkersCount++;
            allWorkersFinished = m_WorkersCount == m_AllWorkersCount;
        }
        m_Mutex.unlock();

        emit itemFinished(success);

        if (allWorkersFinished) {
            Q_ASSERT(m_UploadSemaphore.available() == MAX_PARALLEL_UPLOAD);
            emit percentChanged(100);
            emit percentChangedForItem(index, 100);
            m_PercentDone = 100;
            emit uploadFinished(!m_AnyFailed);
            stopThreads();
        }
    }

    void UploadCoordinator::percentReported(int index, double newPercent, double oldPercent)
    {
        double n = m_UploadThreads.length();
        if (n == 0) { n = 1.0; }
        int percentDone = 0;

        m_PercentMutex.lock();
        {
            m_PercentDone -= oldPercent/n;
            m_PercentDone += newPercent/n;
            percentDone = m_PercentDone;
        }
        m_PercentMutex.unlock();

        emit percentChanged(percentDone);
        emit percentChangedForItem(index, (int)qFloor(newPercent));
    }

    void UploadCoordinator::doRunUpload(const QList<UploadItem*> &uploadItems,
                                        const Encryption::SecretsManager *secretsManager)
    {
        int i = 0;
        foreach (UploadItem *uploadItem, uploadItems) {
            UploadWorker *worker = new UploadWorker(uploadItem, secretsManager, &m_UploadSemaphore, i);
            QThread *thread = new QThread();
            worker->moveToThread(thread);

            QObject::connect(thread, SIGNAL(started()), worker, SLOT(process()));
            QObject::connect(worker, SIGNAL(stopped()), thread, SLOT(quit()));

            QObject::connect(worker, SIGNAL(stopped()), worker, SLOT(deleteLater()));
            QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

            QObject::connect(worker, SIGNAL(finished(int,bool)), this, SLOT(workerFinished(int,bool)));
            QObject::connect(this, SIGNAL(cancelAll()), worker, SLOT(cancel()));

            QObject::connect(worker, SIGNAL(percentChanged(int, double,double)),
                             this, SLOT(percentReported(int, double,double)));

            m_UploadThreads.append(thread);

            thread->start();
            i++;
        }
    }

    void UploadCoordinator::extractFilePathes(const QList<Models::ArtworkMetadata *> &artworkList,
                                              QStringList &filePathes,
                                              QStringList &zipsPathes,
                                              bool includeEPS) const {

        foreach(Models::ArtworkMetadata *metadata, artworkList) {
            QString filepath = metadata->getFilepath();
            filePathes.append(filepath);

            if (includeEPS) {
                QString epsFilepath = filepath.replace(QRegExp("(.*)[.]jpg", Qt::CaseInsensitive), "\\1.eps");
                QString aiFilepath = filepath.replace(QRegExp("(.*)[.]jpg", Qt::CaseInsensitive), "\\1.ai");
                if (QFileInfo(epsFilepath).exists()) {
                    filePathes.append(epsFilepath);
                } else if (QFileInfo(aiFilepath).exists()) {
                    filePathes.append(aiFilepath);
                }
            }

            QString zipPath = Helpers::getArchivePath(filepath);
            zipsPathes.append(zipPath);
        }
    }

    void UploadCoordinator::stopThreads()
    {
        // threads are stopped on worker stopped signal
        // and deleted with thread finished signal binding
        m_UploadThreads.clear();
    }
}

<|endoftext|>