From 772ad1d5f4f1be95a6dd232d7c4af387df7cb88d Mon Sep 17 00:00:00 2001 From: eap Date: Tue, 10 Aug 2021 20:46:27 +0300 Subject: [PATCH] bos #24596 [CEA] New MeshGems license --- src/DriverGMF/DriverGMF_Read.cxx | 34 ++ src/DriverGMF/DriverGMF_Read.hxx | 5 + src/SMESH/MG_ADAPT.cxx | 37 +- src/SMESHUtils/CMakeLists.txt | 2 + src/SMESHUtils/SMESH_MGLicenseKeyGen.cxx | 492 +++++++++++++++++++++++ src/SMESHUtils/SMESH_MGLicenseKeyGen.hxx | 52 +++ 6 files changed, 614 insertions(+), 8 deletions(-) create mode 100644 src/SMESHUtils/SMESH_MGLicenseKeyGen.cxx create mode 100644 src/SMESHUtils/SMESH_MGLicenseKeyGen.hxx diff --git a/src/DriverGMF/DriverGMF_Read.cxx b/src/DriverGMF/DriverGMF_Read.cxx index 175d8100d..c85abbf3c 100644 --- a/src/DriverGMF/DriverGMF_Read.cxx +++ b/src/DriverGMF/DriverGMF_Read.cxx @@ -537,3 +537,37 @@ Driver_Mesh::Status DriverGMF_Read::storeBadNodeIds(const char* gmfKwd, int elem } return DRS_OK; } + +//================================================================================ +/*! + * \brief Return number of mesh entities in a file + */ +//================================================================================ + +bool DriverGMF_Read::GetMeshInfo(smIdType & nbNodes, + smIdType & nbEdges, + smIdType & nbFaces, + smIdType & nbVols) +{ + nbNodes = nbEdges = nbFaces = nbVols = 0; + + Kernel_Utils::Localizer loc; + + int dim, version; + int meshID = GmfOpenMesh( myFile.c_str(), GmfRead, &version, &dim ); + if ( !meshID ) + return false; + + DriverGMF::MeshCloser aMeshCloser( meshID ); // An object closing GMF mesh at destruction + + nbNodes = GmfStatKwd(meshID, GmfVertices ); + nbEdges = GmfStatKwd(meshID, GmfEdges ); + nbFaces = ( GmfStatKwd(meshID, GmfTriangles ) + + GmfStatKwd(meshID, GmfQuadrilaterals )); + nbVols = ( GmfStatKwd(meshID, GmfTetrahedra ) + + GmfStatKwd(meshID, GmfPyramids ) + + GmfStatKwd(meshID, GmfHexahedra ) + + GmfStatKwd(meshID, GmfPrisms )); + + return true; +} diff --git a/src/DriverGMF/DriverGMF_Read.hxx b/src/DriverGMF/DriverGMF_Read.hxx index f055f54b7..8464a5345 100644 --- a/src/DriverGMF/DriverGMF_Read.hxx +++ b/src/DriverGMF/DriverGMF_Read.hxx @@ -57,6 +57,11 @@ public: virtual Status Perform(); + bool GetMeshInfo(smIdType & nbVertex, + smIdType & nbEdge, + smIdType & nbFace, + smIdType & nbVol); + private: Status storeBadNodeIds(const char* gmfKwd, int elemNb, int nb, ...); diff --git a/src/SMESH/MG_ADAPT.cxx b/src/SMESH/MG_ADAPT.cxx index 3530fe477..1e748c534 100644 --- a/src/SMESH/MG_ADAPT.cxx +++ b/src/SMESH/MG_ADAPT.cxx @@ -19,8 +19,11 @@ #include "MG_ADAPT.hxx" -#include "SMESH_File.hxx" -#include "SMESH_Comment.hxx" +#include +#include +#include +#include +#include #include #include @@ -1005,7 +1008,7 @@ std::string MgAdapt::getCommandToRun() cmd += " --"; else cmd += " "; -// std::cout << "--- option: '" << option << ", value: '" << value <<"'"<< std::endl; + // std::cout << "--- option: '" << option << ", value: '" << value <<"'"<< std::endl; cmd += option + " " + value; } } @@ -1015,13 +1018,31 @@ std::string MgAdapt::getCommandToRun() { cmd+= " --verbose "+ ToComment(verbosityLevel); } - //~} -//~cmd+= " >" + // get license key + { + smIdType nbVertex, nbEdge, nbFace, nbVol; + DriverGMF_Read gmfReader; + gmfReader.SetFile( meshIn ); + gmfReader.GetMeshInfo( nbVertex, nbEdge, nbFace, nbVol ); + + std::string errorTxt; + std::string key = SMESHUtils_MGLicenseKeyGen::GetKey( meshIn, + FromSmIdType( nbVertex ), + FromSmIdType( nbEdge ), + FromSmIdType( nbFace ), + FromSmIdType( nbVol ), + errorTxt ); + if ( key.empty() ) + return ToComment( "Problem with library SalomeMeshGemsKeyGenerator: " + errorTxt ); + + cmd += " --key " + key; + } + #ifdef WIN32 - cmd += " < NUL"; + cmd += " < NUL"; #endif -// std::cout << "--- cmd :"<< std::endl; -// std::cout << cmd << std::endl; + // std::cout << "--- cmd :"<< std::endl; + // std::cout << cmd << std::endl; return cmd; } diff --git a/src/SMESHUtils/CMakeLists.txt b/src/SMESHUtils/CMakeLists.txt index 8eb4e3b68..e35033177 100644 --- a/src/SMESHUtils/CMakeLists.txt +++ b/src/SMESHUtils/CMakeLists.txt @@ -62,6 +62,7 @@ SET(SMESHUtils_HEADERS SMESH_Delaunay.hxx SMESH_Indexer.hxx SMESH_BoostTxtArchive.hxx + SMESH_MGLicenseKeyGen.hxx ) # --- sources --- @@ -86,6 +87,7 @@ SET(SMESHUtils_SOURCES SMESH_Slot.cxx SMESH_PolyLine.cxx SMESH_BoostTxtArchive.cxx + SMESH_MGLicenseKeyGen.cxx ) # --- rules --- diff --git a/src/SMESHUtils/SMESH_MGLicenseKeyGen.cxx b/src/SMESHUtils/SMESH_MGLicenseKeyGen.cxx new file mode 100644 index 000000000..e1d2db8d2 --- /dev/null +++ b/src/SMESHUtils/SMESH_MGLicenseKeyGen.cxx @@ -0,0 +1,492 @@ +// Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : SMESHUtils_MGLicenseKeyGen.cxx +// Created : Sat Jul 31 18:54:16 2021 +// Author : Edward AGAPOV (OCC) + +#include "SMESH_MGLicenseKeyGen.hxx" + +#include "SMESH_Comment.hxx" +#include "SMESH_File.hxx" +#include "SMESH_TryCatch.hxx" + +#include +#include + +#include +#include // getenv, system + +#include +namespace boofs = boost::filesystem; + +#ifdef WIN32 + +# include +# include + +# define LibHandle HMODULE +# define LoadLib( name ) LoadLibrary( name ) +# define GetProc GetProcAddress +# define UnLoadLib( handle ) FreeLibrary( handle ); + +#else // WIN32 + +# include + +# define LibHandle void* +# define LoadLib( name ) dlopen( name, RTLD_LAZY | RTLD_LOCAL ) +# define GetProc dlsym +# define UnLoadLib( handle ) dlclose( handle ); + +#endif // WIN32 + +// to retrieve description of exception caught by SMESH_TRY +#undef SMESH_CAUGHT +#define SMESH_CAUGHT error = + + +namespace +{ + static LibHandle theLibraryHandle = nullptr; //!< handle of a loaded library + + const char* theEnvVar = "SALOME_MG_KEYGEN_LIB_PATH"; /* var specifies either full file name + of libSalomeMeshGemsKeyGenerator or + URL to download the library from */ + + const char* theTmpEnvVar = "SALOME_TMP_DIR"; // directory to download the library to + + //----------------------------------------------------------------------------------- + /*! + * \brief Remove library file at destruction in case if it was downloaded from server + */ + //----------------------------------------------------------------------------------- + + struct LibraryFile + { + std::string _name; // full file name + bool _isURL; + + LibraryFile(): _isURL( false ) {} + + ~LibraryFile() + { + if ( _isURL ) + { + if ( theLibraryHandle ) + { + UnLoadLib( theLibraryHandle ); + theLibraryHandle = nullptr; + } + + std::string tmpDir; // tmp dir that should not be removed + if ( const char* libPath = getenv( theTmpEnvVar )) + { + tmpDir = libPath; + while (( !tmpDir.empty() ) && + ( tmpDir.back() == '/' || tmpDir.back() == '\\' )) + tmpDir.pop_back(); + } + + while ( SMESH_File( _name ).remove() ) + { + size_t length = _name.size(); + _name = boofs::path( _name ).parent_path().string(); // goto parent directory + if ( _name.size() == length ) + break; // no more parents + + if ( _name == tmpDir ) + break; // don't remove tmp dir + + if ( !Kernel_Utils::IsEmptyDir( _name )) + break; + } + } + } + }; + + + //================================================================================ + /*! + * \brief Retrieve description of the last error + * \param [out] error - return the description + * \return bool - true if the description found + */ + //================================================================================ + + bool getLastError( std::string& error ) + { +#ifndef WIN32 + + if ( const char* text = dlerror() ) + { + error = text; + return true; + } + return false; + +#else + + DWORD dw = GetLastError(); + void* cstr; + DWORD msgLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &cstr, + 0, + NULL + ); + if ( msgLen > 0 ) + error = (char*) cstr; + + LocalFree(cstr); + + return msgLen; + +#endif + } + + //================================================================================ + /*! + * \brief Adjust file extension according to the platform + */ + //================================================================================ + + bool setExtension( std::string& fileName, std::string& error ) + { + if ( fileName.empty() ) + { + error = "Library file name is empty"; + return false; + } +#if defined(WIN32) + std::string ext = ".dll"; +#elif defined(__APPLE__) + std::string ext = ".dylib"; +#else + std::string ext = ".so"; +#endif + + fileName = fileName.substr( 0, fileName.find_last_of('.')) + ext; + return true; + } + + //================================================================================ + /*! + * \brief Check if library file name looks like an URL + * \param [in,out] libraryFile - holds file name and returns result in _isURL member field + * \return bool - true if the file name looks like an URL + */ + //================================================================================ + + bool isURL( LibraryFile & libraryFile ) + { + enum { SCHEME = 2, AUTHORITY = 4, PATH = 5 }; // sub-strings + std::regex urlRegex ( R"(^(([^:\/?#]+):)?(//([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?)", + std::regex::extended ); + std::smatch matchResult; + + libraryFile._isURL = false; + if ( std::regex_match( libraryFile._name, matchResult, urlRegex )) + libraryFile._isURL = ( !matchResult.str( SCHEME ).empty() && + !matchResult.str( AUTHORITY ).empty() && + !matchResult.str( PATH ).empty() ); + + return libraryFile._isURL; + } + + //================================================================================ + /*! + * \brief Download libraryFile._name URL to SALOME_TMP_DIR + * \param [in,out] libraryFile - holds the URL and returns name of a downloaded file + * \param [out] error - return error description + * \return bool - is a success + */ + //================================================================================ + + bool downloadLib( LibraryFile& libraryFile, std::string & error ) + { + // check if can write into SALOME_TMP_DIR + + std::string tmpDir = Kernel_Utils::GetTmpDirByEnv( theTmpEnvVar ); + if ( tmpDir.empty() || + !Kernel_Utils::IsExists( tmpDir )) + { + error = "Can't download " + libraryFile._name + " as SALOME_TMP_DIR is not correctly set"; + return false; + } + if ( !Kernel_Utils::IsWritable( tmpDir )) + { + error = "Can't download " + libraryFile._name + " as '" + tmpDir + "' is not writable. " + "Check SALOME_TMP_DIR environment variable"; + return false; + } + + // Download + + std::string url = libraryFile._name; + +#ifdef WIN32 + + std::string outFile = tmpDir + "libMeshGemsKeyGenerator.dll"; + + // use wget (== Invoke-WebRequest) PowerShell command available since Windows 7 + std::string psCmd = "wget -Uri " + url + " -OutFile " + outFile; + std::string cmd = "start powershell.exe " + psCmd; + +#else + + std::string outFile = tmpDir + "libMeshGemsKeyGenerator.so"; + + std::string cmd = "wget " + url + " -O " + outFile; + +#endif + + if ( Kernel_Utils::IsExists( outFile )) // remove existing file + { + SMESH_File lib( outFile, /*open=*/false ); + if ( !lib.remove() ) + { + error = lib.error(); + return false; + } + } + + system( cmd.c_str() ); // download + + SMESH_File resultFile( outFile, /*open=*/false ); + bool ok = ( resultFile.exists() && resultFile.size() > 0 ); + + if ( ok ) + libraryFile._name = outFile; + + return ok; + } + + //================================================================================ + /*! + * \brief Load libMeshGemsKeyGenerator.so + * \param [out] error - return error description + * \param [out] libraryFile - return library file name and _isURL flag + * \return bool - is a success + */ + //================================================================================ + + bool loadLibrary( std::string& error, LibraryFile& libraryFile ) + { + if ( theLibraryHandle ) + return true; + + const char* libPath = getenv( theEnvVar ); + if ( !libPath ) + { + error = SMESH_Comment( "Environment variable ") << theEnvVar << " is not set"; + return false; + } + + libraryFile._name = libPath; + // if ( !setExtension( libraryFile._name, error )) // is it necessary? + // return false; + + if ( isURL( libraryFile )) + { + if ( !downloadLib( libraryFile, error )) + { + // try to fix extension + std::string url = libraryFile._name; + if ( !setExtension( libraryFile._name, error )) + return false; + if ( url == libraryFile._name ) + return false; // extension not changed + + if ( !downloadLib( libraryFile, error )) + return false; + } + } + +#if defined( WIN32 ) && defined( UNICODE ) + std::wstring encodePath = Kernel_Utils::utf8_decode_s( libraryFile._name ); + const wchar_t* path = encodePath.c_str(); +#else + const char* path = libraryFile._name.c_str(); +#endif + + theLibraryHandle = LoadLib( path ); + if ( !theLibraryHandle ) + { + if ( ! getLastError( error )) + error = "Can't load library '" + libraryFile._name + "'"; + } + + return theLibraryHandle; + } + +} // anonymous namespace + + +namespace SMESHUtils_MGLicenseKeyGen // API implementation +{ + //================================================================================ + /*! + * \brief Sign a CAD + * \param [in] meshgems_cad - pointer to a MG CAD object (meshgems_cad_t) + * \param [out] error - return error description + * \return bool - is a success + */ + //================================================================================ + + bool SignCAD( void* meshgems_cad, std::string& error ) + { + LibraryFile libraryFile; + if ( !loadLibrary( error, libraryFile )) + return false; + + typedef bool (*SignFun)(void* ); + SignFun signFun = (SignFun) GetProc( theLibraryHandle, "SignCAD" ); + if ( !signFun ) + { + if ( ! getLastError( error )) + error = SMESH_Comment( "Can't find symbol 'SignCAD' in '") << getenv( theEnvVar ) << "'"; + } + + bool ok; + + SMESH_TRY; + + ok = signFun( meshgems_cad ); + + SMESH_CATCH( SMESH::returnError ); + + if ( !error.empty() ) + ok = false; + else if ( !ok ) + error = "SignCAD() failed (located in '" + libraryFile._name + "')"; + + return ok; + } + + //================================================================================ + /*! + * \brief Sign a mesh + * \param [in] meshgems_mesh - pointer to a MG mesh (meshgems_mesh_t) + * \param [out] error - return error description + * \return bool - is a success + */ + //================================================================================ + + bool SignMesh( void* meshgems_mesh, std::string& error ) + { + LibraryFile libraryFile; + if ( !loadLibrary( error, libraryFile )) + return false; + + typedef bool (*SignFun)(void* ); + SignFun signFun = (SignFun) GetProc( theLibraryHandle, "SignMesh" ); + if ( !signFun ) + { + if ( ! getLastError( error )) + error = SMESH_Comment( "Can't find symbol 'SignMesh' in '") << getenv( theEnvVar ) << "'"; + } + bool ok; + + SMESH_TRY; + + ok = signFun( meshgems_mesh ); + + SMESH_CATCH( SMESH::returnError ); + + if ( !error.empty() ) + ok = false; + else if ( !ok ) + error = "SignMesh() failed (located in '" + libraryFile._name + "')"; + + return ok; + } + + //================================================================================ + /*! + * \brief Return a license key to pass as argument to a MG mesher executable + * \param [in] gmfFile - path to an input mesh file + * \param [in] nb* - nb of entities in the input mesh + * \param [out] error - return error description + * \return std::string - the key + */ + //================================================================================ + + std::string GetKey(const std::string& gmfFile, + int nbVertex, + int nbEdge, + int nbFace, + int nbVol, + std::string& error) + { + std::string key; + LibraryFile libraryFile; + if ( !loadLibrary( error, libraryFile )) + return key; + + typedef std::string (*GetKeyFun)(std::string const &, int, int, int, int ); + GetKeyFun keyFun = (GetKeyFun) GetProc( theLibraryHandle, "GetKey" ); + if ( !keyFun ) + { + if ( ! getLastError( error )) + error = SMESH_Comment( "Can't find symbol 'GetKey' in '") << getenv( theEnvVar ) << "'"; + } + key = keyFun( gmfFile, nbVertex, nbEdge, nbFace, nbVol ); + + if ( key.empty() ) + error = "GetKey() failed (located in '" + libraryFile._name + "')"; + + return key; + } + + //================================================================================ + /*! + * \brief Return false if libMeshGemsKeyGenerator.so is not functional + * \param [out] error - return error description + * \return bool - is a success + */ + //================================================================================ + + bool CheckKeyGenLibrary( std::string& error ) + { + return !GetKey("",4,0,2,0,error ).empty(); + } + + //================================================================================ + /*! + * \brief Return KeyGenerator library name + */ + //================================================================================ + + std::string GetLibraryName() + { + std::string libName, error; + if ( const char* libPath = getenv( theEnvVar )) + { + libName = Kernel_Utils::GetBaseName( libPath ); + } + else + { + libName = "libSalomeMeshGemsKeyGenerator"; + } + setExtension( libName, error ); + return libName; + } +} diff --git a/src/SMESHUtils/SMESH_MGLicenseKeyGen.hxx b/src/SMESHUtils/SMESH_MGLicenseKeyGen.hxx new file mode 100644 index 000000000..c81fa3090 --- /dev/null +++ b/src/SMESHUtils/SMESH_MGLicenseKeyGen.hxx @@ -0,0 +1,52 @@ +// Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// 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 +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : SMESH_MGLicenseKeyGen.hxx +// Created : Sat Jul 31 18:41:04 2021 +// Author : Edward AGAPOV (OCC) + +#ifndef __SMESHUtils_MGLicenseKeyGen_HXX__ +#define __SMESHUtils_MGLicenseKeyGen_HXX__ + +#include "SMESH_Utils.hxx" + +#include + +/*! + * \brief Manage loading libSalomeMeshGemsKeyGenerator.[so|dll] and sing MeshGems CAD or mesh + */ + +namespace SMESHUtils_MGLicenseKeyGen +{ + SMESHUtils_EXPORT bool SignCAD( void* meshgems_cad, std::string& error ); + + SMESHUtils_EXPORT bool SignMesh( void* meshgems_mesh, std::string& error ); + + SMESHUtils_EXPORT std::string GetKey(const std::string& gmfFile, + int nbVertex, + int nbEdge, + int nbFace, + int nbVol, + std::string& error); + + SMESHUtils_EXPORT bool CheckKeyGeLibrary( std::string& error ); + + SMESHUtils_EXPORT std::string GetLibraryName(); +} + +#endif -- 2.39.2