Merge branch 'master' of github.com:InvictusInnovations/fc
Conflicts: .gitignore
This commit is contained in:
commit
eb022cef27
49 changed files with 1537 additions and 237 deletions
11
.gitignore
vendored
11
.gitignore
vendored
|
|
@ -33,16 +33,23 @@ ZERO_CHECK
|
|||
Debug/
|
||||
Release/
|
||||
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
*.cmake
|
||||
*.cbp
|
||||
|
||||
libfc.a
|
||||
libfc_debug.a
|
||||
|
||||
*.sw*
|
||||
|
||||
fc_automoc.cpp
|
||||
git_revision.cpp
|
||||
GitSHA3.cpp
|
||||
|
||||
*.sw*
|
||||
lzma_test
|
||||
ntp_test
|
||||
task_cancel_test
|
||||
udt_client
|
||||
udt_server
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ endif()
|
|||
SET (ORIGINAL_LIB_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
|
||||
SET(BOOST_COMPONENTS)
|
||||
LIST(APPEND BOOST_COMPONENTS thread date_time system filesystem program_options signals serialization chrono unit_test_framework context locale)
|
||||
LIST(APPEND BOOST_COMPONENTS thread date_time system filesystem program_options signals serialization chrono unit_test_framework context locale iostreams)
|
||||
|
||||
IF( WIN32 )
|
||||
MESSAGE(STATUS "Configuring fc to build on Win32")
|
||||
|
|
@ -147,10 +147,10 @@ set( fc_sources
|
|||
src/crypto/rand.cpp
|
||||
src/crypto/salsa20.cpp
|
||||
src/crypto/scrypt.cpp
|
||||
# commented out until committed
|
||||
# src/crypto/romix.cpp
|
||||
src/crypto/romix.cpp
|
||||
src/network/tcp_socket.cpp
|
||||
src/network/udp_socket.cpp
|
||||
src/network/udt_socket.cpp
|
||||
src/network/http/http_connection.cpp
|
||||
src/network/http/http_server.cpp
|
||||
src/network/ntp.cpp
|
||||
|
|
@ -182,6 +182,7 @@ list(APPEND sources "${CMAKE_CURRENT_BINARY_DIR}/git_revision.cpp")
|
|||
list(APPEND sources ${fc_headers})
|
||||
|
||||
add_subdirectory( vendor/easylzma )
|
||||
add_subdirectory( vendor/scrypt-jane )
|
||||
add_subdirectory( vendor/udt4 )
|
||||
|
||||
setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC DONT_INSTALL_LIBRARY )
|
||||
|
|
@ -199,10 +200,9 @@ ELSE()
|
|||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall")
|
||||
|
||||
IF(APPLE)
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -std=c++11 -stdlib=libc++ -Wall")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++ -Wall")
|
||||
ELSE()
|
||||
target_compile_options(fc PUBLIC -std=c++11 -Wall -fnon-call-exceptions)
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -fnon-call-exceptions")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
|
|
@ -220,18 +220,24 @@ target_include_directories(fc
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/udt4/src
|
||||
)
|
||||
|
||||
target_link_libraries( fc PUBLIC easylzma_static ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library})
|
||||
target_link_libraries( fc PUBLIC easylzma_static scrypt udt ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES} ${PLATFORM_SPECIFIC_LIBS} ${RPCRT4} ${CMAKE_DL_LIBS} ${rt_library})
|
||||
|
||||
add_executable( ntp_test ntp_test.cpp )
|
||||
target_link_libraries( ntp_test fc )
|
||||
|
||||
add_executable( task_cancel_test tests/task_cancel.cpp )
|
||||
target_link_libraries( task_cancel_test fc )
|
||||
|
||||
#include_directories( vendor/udt4/src )
|
||||
|
||||
#add_executable( udt_server tests/udt_server.cpp )
|
||||
#target_link_libraries( udt_server fc udt )
|
||||
add_executable( udt_server tests/udts.cpp )
|
||||
target_link_libraries( udt_server fc udt )
|
||||
|
||||
#add_executable( udt_client tests/udt_client.cpp )
|
||||
#target_link_libraries( udt_client fc udt )
|
||||
add_executable( udt_client tests/udtc.cpp )
|
||||
target_link_libraries( udt_client fc udt )
|
||||
|
||||
add_executable( lzma_test tests/lzma_test.cpp )
|
||||
target_link_libraries( lzma_test fc )
|
||||
|
||||
#add_executable( test_compress tests/compress.cpp )
|
||||
#target_link_libraries( test_compress fc )
|
||||
|
|
|
|||
|
|
@ -79,11 +79,11 @@ namespace asio {
|
|||
* @return the number of bytes read.
|
||||
*/
|
||||
template<typename AsyncReadStream, typename MutableBufferSequence>
|
||||
size_t read_some(AsyncReadStream& s, const MutableBufferSequence& buf)
|
||||
future<size_t> read_some(AsyncReadStream& s, const MutableBufferSequence& buf)
|
||||
{
|
||||
promise<size_t>::ptr p(new promise<size_t>("fc::asio::async_read_some"));
|
||||
s.async_read_some(buf, boost::bind(detail::read_write_handler, p, _1, _2));
|
||||
return p->wait();
|
||||
return p;//->wait();
|
||||
}
|
||||
|
||||
template<typename AsyncReadStream, typename MutableBufferSequence>
|
||||
|
|
@ -117,10 +117,10 @@ namespace asio {
|
|||
* @return the number of bytes written
|
||||
*/
|
||||
template<typename AsyncWriteStream, typename ConstBufferSequence>
|
||||
size_t write_some( AsyncWriteStream& s, const ConstBufferSequence& buf ) {
|
||||
future<size_t> write_some( AsyncWriteStream& s, const ConstBufferSequence& buf ) {
|
||||
promise<size_t>::ptr p(new promise<size_t>("fc::asio::write_some"));
|
||||
s.async_write_some( buf, boost::bind( detail::read_write_handler, p, _1, _2 ) );
|
||||
return p->wait();
|
||||
return p; //->wait();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -183,7 +183,7 @@ namespace asio {
|
|||
|
||||
virtual size_t readsome( char* buf, size_t len )
|
||||
{
|
||||
auto r = fc::asio::read_some(*_stream, boost::asio::buffer(buf, len) );
|
||||
auto r = fc::asio::read_some(*_stream, boost::asio::buffer(buf, len) ).wait();
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
@ -200,7 +200,7 @@ namespace asio {
|
|||
|
||||
virtual size_t writesome( const char* buf, size_t len )
|
||||
{
|
||||
return fc::asio::write_some(*_stream, boost::asio::const_buffers_1(buf, len) );
|
||||
return fc::asio::write_some(*_stream, boost::asio::const_buffers_1(buf, len) ).wait();
|
||||
}
|
||||
|
||||
virtual void close(){ _stream->close(); }
|
||||
|
|
|
|||
|
|
@ -1,9 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include <fc/filesystem.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace fc {
|
||||
|
||||
std::vector<char> lzma_compress( const std::vector<char>& in );
|
||||
std::vector<char> lzma_decompress( const std::vector<char>& compressed );
|
||||
std::vector<char> lzma_compress( const std::vector<char>& in );
|
||||
std::vector<char> lzma_decompress( const std::vector<char>& compressed );
|
||||
|
||||
void lzma_compress_file( const path& src_path,
|
||||
const path& dst_path,
|
||||
unsigned char level = 5,
|
||||
unsigned int dict_size = (1 << 20) );
|
||||
|
||||
void lzma_decompress_file( const path& src_path,
|
||||
const path& dst_path );
|
||||
|
||||
} // namespace fc
|
||||
|
|
|
|||
|
|
@ -37,12 +37,12 @@ namespace fc {
|
|||
fc::fwd<impl,96> my;
|
||||
};
|
||||
|
||||
int aes_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
|
||||
unsigned char *iv, unsigned char *ciphertext);
|
||||
int aes_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
|
||||
unsigned char *iv, unsigned char *plaintext);
|
||||
int aes_cfb_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
|
||||
unsigned char *iv, unsigned char *plaintext);
|
||||
unsigned aes_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
|
||||
unsigned char *iv, unsigned char *ciphertext);
|
||||
unsigned aes_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
|
||||
unsigned char *iv, unsigned char *plaintext);
|
||||
unsigned aes_cfb_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
|
||||
unsigned char *iv, unsigned char *plaintext);
|
||||
|
||||
std::vector<char> aes_encrypt( const fc::sha512& key, const std::vector<char>& plain_text );
|
||||
std::vector<char> aes_decrypt( const fc::sha512& key, const std::vector<char>& cipher_text );
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
namespace fc {
|
||||
|
|
@ -56,21 +57,21 @@ namespace fc {
|
|||
class romix
|
||||
{
|
||||
public:
|
||||
romix(u_int32_t memReqts, u_int32_t numIter, std::string salt);
|
||||
romix(uint32_t memReqts, uint32_t numIter, std::string salt);
|
||||
|
||||
std::string deriveKey_OneIter(std::string const & password);
|
||||
std::string deriveKey(std::string const & password);
|
||||
|
||||
private:
|
||||
u_int32_t hashOutputBytes_;
|
||||
u_int32_t kdfOutputBytes_; // size of final key data
|
||||
uint32_t hashOutputBytes_;
|
||||
uint32_t kdfOutputBytes_; // size of final key data
|
||||
|
||||
u_int32_t memoryReqtBytes_;
|
||||
u_int32_t sequenceCount_;
|
||||
uint32_t memoryReqtBytes_;
|
||||
uint32_t sequenceCount_;
|
||||
std::string salt_; // prob not necessary amidst numIter, memReqts
|
||||
// but I guess it can't hurt
|
||||
|
||||
u_int32_t numIterations_; // We set the ROMIX params for a given memory
|
||||
uint32_t numIterations_; // We set the ROMIX params for a given memory
|
||||
// req't. Then run it numIter times to meet
|
||||
// the computation-time req't
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace fc {
|
||||
|
||||
void scrypt_derive_key ( const std::vector<unsigned char> &passphrase, const std::vector<unsigned char> &salt,
|
||||
unsigned int n, unsigned int r, unsigned int p, std::vector<unsigned char> &key );
|
||||
void scrypt_derive_key( const std::vector<unsigned char>& passphrase, const std::vector<unsigned char>& salt,
|
||||
unsigned int n, unsigned int r, unsigned int p, std::vector<unsigned char>& key );
|
||||
|
||||
} // namespace fc
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ namespace fc
|
|||
std_exception_code = 13,
|
||||
invalid_operation_exception_code = 14,
|
||||
unknown_host_exception_code = 15,
|
||||
null_optional_code = 16
|
||||
null_optional_code = 16,
|
||||
udt_error_code = 17
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -281,6 +282,7 @@ namespace fc
|
|||
FC_DECLARE_EXCEPTION( assert_exception, assert_exception_code, "Assert Exception" );
|
||||
FC_DECLARE_EXCEPTION( eof_exception, eof_exception_code, "End Of File" );
|
||||
FC_DECLARE_EXCEPTION( null_optional, null_optional_code, "null optional" );
|
||||
FC_DECLARE_EXCEPTION( udt_exception, udt_error_code, "UDT error" );
|
||||
|
||||
std::string except_str();
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ namespace fc
|
|||
* @return *this
|
||||
*/
|
||||
virtual iprocess& exec( const path& exe, std::vector<std::string> args,
|
||||
const path& work_dir = path(), exec_opts opts = open_all ) = 0;
|
||||
const path& work_dir = path(), int opts = open_all ) = 0;
|
||||
|
||||
/**
|
||||
* @return blocks until the process exits
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace fc {
|
|||
virtual iprocess& exec( const fc::path& exe,
|
||||
std::vector<std::string> args,
|
||||
const fc::path& work_dir = fc::path(),
|
||||
exec_opts opts = open_all );
|
||||
int opts = open_all );
|
||||
|
||||
|
||||
virtual int result(const microseconds& timeout = microseconds::maximum());
|
||||
|
|
|
|||
|
|
@ -19,12 +19,21 @@ struct unsigned_int {
|
|||
|
||||
uint32_t value;
|
||||
|
||||
friend bool operator==( const unsigned_int& i, const uint32_t& v ) { return v == i.value; }
|
||||
friend bool operator!=( const unsigned_int& i, const uint32_t& v ) { return v != i.value; }
|
||||
friend bool operator<( const unsigned_int& i, const uint32_t& v ) { return v < i.value; }
|
||||
friend bool operator>=( const unsigned_int& i, const uint32_t& v ) { return v >= i.value; }
|
||||
friend bool operator<( const unsigned_int& i, const unsigned_int& v ) { return v < i.value; }
|
||||
friend bool operator>=( const unsigned_int& i, const unsigned_int& v ) { return v >= i.value; }
|
||||
friend bool operator==( const unsigned_int& i, const uint32_t& v ) { return i.value == v; }
|
||||
friend bool operator==( const uint32_t& i, const unsigned_int& v ) { return i == v.value; }
|
||||
friend bool operator==( const unsigned_int& i, const unsigned_int& v ) { return i.value == v.value; }
|
||||
|
||||
friend bool operator!=( const unsigned_int& i, const uint32_t& v ) { return i.value != v; }
|
||||
friend bool operator!=( const uint32_t& i, const unsigned_int& v ) { return i != v.value; }
|
||||
friend bool operator!=( const unsigned_int& i, const unsigned_int& v ) { return i.value != v.value; }
|
||||
|
||||
friend bool operator<( const unsigned_int& i, const uint32_t& v ) { return i.value < v; }
|
||||
friend bool operator<( const uint32_t& i, const unsigned_int& v ) { return i < v.value; }
|
||||
friend bool operator<( const unsigned_int& i, const unsigned_int& v ) { return i.value < v.value; }
|
||||
|
||||
friend bool operator>=( const unsigned_int& i, const uint32_t& v ) { return i.value >= v; }
|
||||
friend bool operator>=( const uint32_t& i, const unsigned_int& v ) { return i >= v.value; }
|
||||
friend bool operator>=( const unsigned_int& i, const unsigned_int& v ) { return i.value >= v.value; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -41,6 +50,22 @@ struct signed_int {
|
|||
signed_int& operator++(){ ++value; return *this; }
|
||||
|
||||
int32_t value;
|
||||
|
||||
friend bool operator==( const signed_int& i, const int32_t& v ) { return i.value == v; }
|
||||
friend bool operator==( const int32_t& i, const signed_int& v ) { return i == v.value; }
|
||||
friend bool operator==( const signed_int& i, const signed_int& v ) { return i.value == v.value; }
|
||||
|
||||
friend bool operator!=( const signed_int& i, const int32_t& v ) { return i.value != v; }
|
||||
friend bool operator!=( const int32_t& i, const signed_int& v ) { return i != v.value; }
|
||||
friend bool operator!=( const signed_int& i, const signed_int& v ) { return i.value != v.value; }
|
||||
|
||||
friend bool operator<( const signed_int& i, const int32_t& v ) { return i.value < v; }
|
||||
friend bool operator<( const int32_t& i, const signed_int& v ) { return i < v.value; }
|
||||
friend bool operator<( const signed_int& i, const signed_int& v ) { return i.value < v.value; }
|
||||
|
||||
friend bool operator>=( const signed_int& i, const int32_t& v ) { return i.value >= v; }
|
||||
friend bool operator>=( const int32_t& i, const signed_int& v ) { return i >= v.value; }
|
||||
friend bool operator>=( const signed_int& i, const signed_int& v ) { return i.value >= v.value; }
|
||||
};
|
||||
|
||||
class variant;
|
||||
|
|
@ -64,4 +89,13 @@ namespace std
|
|||
return std::hash<int32_t>()(a.value);
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct hash<fc::unsigned_int>
|
||||
{
|
||||
public:
|
||||
size_t operator()(const fc::signed_int &a) const
|
||||
{
|
||||
return std::hash<uint32_t>()(a.value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <fc/filesystem.hpp>
|
||||
#include <fc/log/appender.hpp>
|
||||
#include <fc/log/logger.hpp>
|
||||
#include <fc/filesystem.hpp>
|
||||
#include <fc/time.hpp>
|
||||
|
||||
namespace fc {
|
||||
|
||||
class varaint;
|
||||
|
||||
class file_appender : public appender {
|
||||
public:
|
||||
struct config {
|
||||
|
|
@ -16,10 +16,14 @@ class file_appender : public appender {
|
|||
fc::path filename;
|
||||
bool flush;
|
||||
bool truncate;
|
||||
bool rotate;
|
||||
microseconds rotation_interval;
|
||||
microseconds rotation_limit;
|
||||
bool rotation_compression;
|
||||
};
|
||||
file_appender( const variant& args );
|
||||
~file_appender();
|
||||
virtual void log( const log_message& m );
|
||||
virtual void log( const log_message& m )override;
|
||||
|
||||
private:
|
||||
class impl;
|
||||
|
|
@ -28,4 +32,5 @@ class file_appender : public appender {
|
|||
} // namespace fc
|
||||
|
||||
#include <fc/reflect/reflect.hpp>
|
||||
FC_REFLECT( fc::file_appender::config, (format)(filename)(flush)(truncate) )
|
||||
FC_REFLECT( fc::file_appender::config,
|
||||
(format)(filename)(flush)(truncate)(rotate)(rotation_interval)(rotation_limit)(rotation_compression) )
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <fc/crypto/sha1.hpp>
|
||||
#include <fc/io/raw_fwd.hpp>
|
||||
#include <fc/crypto/city.hpp>
|
||||
#include <fc/reflect/reflect.hpp>
|
||||
|
||||
namespace fc {
|
||||
|
||||
|
|
@ -78,6 +79,7 @@ namespace fc {
|
|||
void to_variant( const ip::address& var, variant& vo );
|
||||
void from_variant( const variant& var, ip::address& vo );
|
||||
|
||||
|
||||
namespace raw
|
||||
{
|
||||
template<typename Stream>
|
||||
|
|
@ -110,7 +112,9 @@ namespace fc {
|
|||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace fc
|
||||
FC_REFLECT_TYPENAME( fc::ip::address )
|
||||
FC_REFLECT_TYPENAME( fc::ip::endpoint )
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ namespace fc {
|
|||
#ifdef _WIN64
|
||||
fc::fwd<impl,0x78> my;
|
||||
#else
|
||||
fc::fwd<impl,0x4c> my;
|
||||
fc::fwd<impl,0x54> my;
|
||||
#endif
|
||||
};
|
||||
typedef std::shared_ptr<tcp_socket> tcp_socket_ptr;
|
||||
|
|
|
|||
67
include/fc/network/udt_socket.hpp
Normal file
67
include/fc/network/udt_socket.hpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#pragma once
|
||||
#include <fc/utility.hpp>
|
||||
#include <fc/fwd.hpp>
|
||||
#include <fc/io/iostream.hpp>
|
||||
#include <fc/time.hpp>
|
||||
#include <fc/noncopyable.hpp>
|
||||
|
||||
namespace fc {
|
||||
namespace ip { class endpoint; }
|
||||
|
||||
class udt_socket : public virtual iostream, public noncopyable
|
||||
{
|
||||
public:
|
||||
udt_socket();
|
||||
~udt_socket();
|
||||
|
||||
void bind( const fc::ip::endpoint& local_endpoint );
|
||||
void connect_to( const fc::ip::endpoint& remote_endpoint );
|
||||
|
||||
fc::ip::endpoint remote_endpoint() const;
|
||||
fc::ip::endpoint local_endpoint() const;
|
||||
|
||||
void get( char& c )
|
||||
{
|
||||
read( &c, 1 );
|
||||
}
|
||||
|
||||
|
||||
/// istream interface
|
||||
/// @{
|
||||
virtual size_t readsome( char* buffer, size_t max );
|
||||
virtual bool eof()const;
|
||||
/// @}
|
||||
|
||||
/// ostream interface
|
||||
/// @{
|
||||
virtual size_t writesome( const char* buffer, size_t len );
|
||||
virtual void flush();
|
||||
virtual void close();
|
||||
/// @}
|
||||
|
||||
void open();
|
||||
bool is_open()const;
|
||||
|
||||
private:
|
||||
friend class udt_server;
|
||||
int _udt_socket_id;
|
||||
};
|
||||
typedef std::shared_ptr<udt_socket> udt_socket_ptr;
|
||||
|
||||
class udt_server : public noncopyable
|
||||
{
|
||||
public:
|
||||
udt_server();
|
||||
~udt_server();
|
||||
|
||||
void close();
|
||||
void accept( udt_socket& s );
|
||||
|
||||
void listen( const fc::ip::endpoint& ep );
|
||||
fc::ip::endpoint local_endpoint() const;
|
||||
|
||||
private:
|
||||
int _udt_socket_id;
|
||||
};
|
||||
|
||||
} // fc
|
||||
14
include/fc/noncopyable.hpp
Normal file
14
include/fc/noncopyable.hpp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
namespace fc
|
||||
{
|
||||
class noncopyable
|
||||
{
|
||||
public:
|
||||
noncopyable(){}
|
||||
private:
|
||||
noncopyable( const noncopyable& ) = delete;
|
||||
noncopyable& operator=( const noncopyable& ) = delete;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -4,6 +4,8 @@
|
|||
namespace fc {
|
||||
class value;
|
||||
class exception;
|
||||
namespace ip { class address; }
|
||||
|
||||
template<typename T> class get_typename{};
|
||||
template<> struct get_typename<int32_t> { static const char* name() { return "int32_t"; } };
|
||||
template<> struct get_typename<int64_t> { static const char* name() { return "int64_t"; } };
|
||||
|
|
|
|||
|
|
@ -107,6 +107,17 @@ namespace fc { namespace rpc {
|
|||
const variant& a7
|
||||
);
|
||||
|
||||
future<variant> async_call( const fc::string& method,
|
||||
const variant& a1,
|
||||
const variant& a2,
|
||||
const variant& a3,
|
||||
const variant& a4,
|
||||
const variant& a5,
|
||||
const variant& a6,
|
||||
const variant& a7,
|
||||
const variant& a8
|
||||
);
|
||||
|
||||
template<typename Result>
|
||||
Result call( const fc::string& method,
|
||||
const variants& args,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ namespace fc {
|
|||
#if !defined(BOOST_NO_TEMPLATE_ALIASES)
|
||||
template<typename T>
|
||||
using signal = boost::signals2::signal<T>;
|
||||
|
||||
using scoped_connection = boost::signals2::scoped_connection;
|
||||
#else
|
||||
/** Workaround for missing Template Aliases feature in the VS 2012.
|
||||
\warning Class defined below cannot have defined constructor (even base class has it)
|
||||
|
|
|
|||
|
|
@ -184,14 +184,15 @@ namespace fc {
|
|||
/// @post ready()
|
||||
/// @throws timeout
|
||||
const T& wait( const microseconds& timeout = microseconds::maximum() )const {
|
||||
return m_prom->wait(timeout);
|
||||
return m_prom->wait(timeout);
|
||||
}
|
||||
|
||||
/// @pre valid()
|
||||
/// @post ready()
|
||||
/// @throws timeout
|
||||
const T& wait_until( const time_point& tp )const {
|
||||
return m_prom->wait_until(tp);
|
||||
if( m_prom )
|
||||
return m_prom->wait_until(tp);
|
||||
}
|
||||
|
||||
bool valid()const { return !!m_prom; }
|
||||
|
|
@ -203,7 +204,16 @@ namespace fc {
|
|||
bool error()const { return m_prom->error(); }
|
||||
|
||||
void cancel()const { if( m_prom ) m_prom->cancel(); }
|
||||
bool canceled()const { return m_prom->canceled(); }
|
||||
bool canceled()const { if( m_prom ) return m_prom->canceled(); else return true;}
|
||||
|
||||
void cancel_and_wait()
|
||||
{
|
||||
if( valid() )
|
||||
{
|
||||
cancel();
|
||||
wait();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre valid()
|
||||
|
|
@ -239,7 +249,8 @@ namespace fc {
|
|||
/// @post ready()
|
||||
/// @throws timeout
|
||||
void wait( const microseconds& timeout = microseconds::maximum() ){
|
||||
m_prom->wait(timeout);
|
||||
if( m_prom )
|
||||
m_prom->wait(timeout);
|
||||
}
|
||||
|
||||
/// @pre valid()
|
||||
|
|
@ -250,7 +261,13 @@ namespace fc {
|
|||
}
|
||||
|
||||
bool valid()const { return !!m_prom; }
|
||||
bool canceled()const { return m_prom->canceled(); }
|
||||
bool canceled()const { return m_prom ? m_prom->canceled() : true; }
|
||||
|
||||
void cancel_and_wait()
|
||||
{
|
||||
cancel();
|
||||
wait();
|
||||
}
|
||||
|
||||
/// @pre valid()
|
||||
bool ready()const { return m_prom->ready(); }
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace fc {
|
|||
|
||||
class thread {
|
||||
public:
|
||||
thread( const char* name = "" );
|
||||
thread( const std::string& name = "" );
|
||||
thread( thread&& m );
|
||||
thread& operator=(thread&& t );
|
||||
|
||||
|
|
@ -175,6 +175,10 @@ namespace fc {
|
|||
auto async( Functor&& f, const char* desc ="", priority prio = priority()) -> fc::future<decltype(f())> {
|
||||
return fc::thread::current().async( fc::forward<Functor>(f), desc, prio );
|
||||
}
|
||||
template<typename Functor>
|
||||
auto schedule( Functor&& f, const fc::time_point& t, const char* desc ="", priority prio = priority()) -> fc::future<decltype(f())> {
|
||||
return fc::thread::current().schedule( fc::forward<Functor>(f), t, desc, prio );
|
||||
}
|
||||
|
||||
} // end namespace fc
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,8 @@ namespace fc {
|
|||
friend bool operator != ( const time_point_sec& a, const time_point_sec& b ) { return a.utc_seconds != b.utc_seconds; }
|
||||
time_point_sec& operator += ( uint32_t m ) { utc_seconds+=m; return *this; }
|
||||
time_point_sec& operator -= ( uint32_t m ) { utc_seconds-=m; return *this; }
|
||||
time_point_sec operator+( uint32_t offset ) { return time_point_sec(utc_seconds + offset); }
|
||||
time_point_sec operator +( uint32_t offset )const { return time_point_sec(utc_seconds + offset); }
|
||||
time_point_sec operator -( uint32_t offset )const { return time_point_sec(utc_seconds - offset); }
|
||||
|
||||
friend time_point operator - ( const time_point_sec& t, const microseconds& m ) { return time_point(t) - m; }
|
||||
friend microseconds operator - ( const time_point_sec& t, const time_point_sec& m ) { return time_point(t) - time_point(m); }
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ int main( int argc, char** argv )
|
|||
auto hours = delta.count() / 1000000 / 60 / 60;
|
||||
auto seconds = delta.count() / 1000000;
|
||||
auto msec= delta.count() / 1000;
|
||||
idump( (fc::time_point::now() ) );
|
||||
idump( (ntp_time)(delta)(msec)(seconds)(minutes)(hours) );
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
#include <boost/iostreams/device/mapped_file.hpp>
|
||||
#include <fc/compress/lzma.hpp>
|
||||
#include <fc/exception/exception.hpp>
|
||||
|
||||
#include <fc/io/fstream.hpp>
|
||||
#include <lzma_c.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace fc {
|
||||
|
||||
std::vector<char> lzma_compress(const std::vector<char>& in)
|
||||
|
|
@ -50,4 +53,148 @@ std::vector<char> lzma_decompress( const std::vector<char>& compressed )
|
|||
return out;
|
||||
}
|
||||
|
||||
struct lzma_file_ctx
|
||||
{
|
||||
const unsigned char* src_buf;
|
||||
size_t src_len;
|
||||
|
||||
path dst_path;
|
||||
};
|
||||
|
||||
static int lzma_file_input_callback( void* input_ctx, void* input_buf, size_t* input_len )
|
||||
{
|
||||
FC_ASSERT( input_ctx != NULL );
|
||||
FC_ASSERT( input_buf != NULL );
|
||||
|
||||
const auto ctx = ( struct lzma_file_ctx* )input_ctx;
|
||||
const auto size = ( ctx->src_len < *input_len ) ? ctx->src_len : *input_len;
|
||||
|
||||
if( size > 0 )
|
||||
{
|
||||
memcpy( input_buf, ( void * )ctx->src_buf, size );
|
||||
ctx->src_buf += size;
|
||||
ctx->src_len -= size;
|
||||
}
|
||||
|
||||
*input_len = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t lzma_file_output_callback( void* output_ctx, const void* output_buf, size_t output_len )
|
||||
{
|
||||
FC_ASSERT( output_ctx != NULL );
|
||||
FC_ASSERT( output_buf != NULL );
|
||||
|
||||
const auto ctx = ( struct lzma_file_ctx* )output_ctx;
|
||||
|
||||
if( output_len > 0 )
|
||||
{
|
||||
size_t dst_len = 0;
|
||||
if( !exists( ctx->dst_path ) )
|
||||
{
|
||||
ofstream fs( ctx->dst_path );
|
||||
fs.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
dst_len = file_size( ctx->dst_path );
|
||||
}
|
||||
|
||||
resize_file( ctx->dst_path, dst_len + output_len );
|
||||
|
||||
boost::iostreams::mapped_file_sink dst_file;
|
||||
dst_file.open( ctx->dst_path.string() );
|
||||
FC_ASSERT( dst_file.is_open() );
|
||||
|
||||
memcpy( ( void* )(dst_file.data() + dst_len), output_buf, output_len);
|
||||
|
||||
dst_file.close();
|
||||
}
|
||||
|
||||
return output_len;
|
||||
}
|
||||
|
||||
void lzma_compress_file( const path& src_path,
|
||||
const path& dst_path,
|
||||
unsigned char level,
|
||||
unsigned int dict_size )
|
||||
{
|
||||
FC_ASSERT( exists( src_path ) );
|
||||
FC_ASSERT( !exists( dst_path ) );
|
||||
|
||||
boost::iostreams::mapped_file_source src_file;
|
||||
src_file.open( src_path.string() );
|
||||
FC_ASSERT( src_file.is_open() );
|
||||
|
||||
elzma_compress_handle handle = NULL;
|
||||
handle = elzma_compress_alloc();
|
||||
FC_ASSERT( handle != NULL );
|
||||
|
||||
struct lzma_file_ctx ctx;
|
||||
ctx.src_buf = ( const unsigned char* )src_file.data();
|
||||
ctx.src_len = src_file.size();
|
||||
ctx.dst_path = dst_path;
|
||||
|
||||
auto rc = elzma_compress_config( handle,
|
||||
ELZMA_LC_DEFAULT,
|
||||
ELZMA_LP_DEFAULT,
|
||||
ELZMA_PB_DEFAULT,
|
||||
level,
|
||||
dict_size,
|
||||
elzma_file_format::ELZMA_lzma,
|
||||
ctx.src_len );
|
||||
|
||||
try
|
||||
{
|
||||
FC_ASSERT( rc == ELZMA_E_OK );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
elzma_compress_free( &handle );
|
||||
throw;
|
||||
}
|
||||
|
||||
rc = elzma_compress_run( handle,
|
||||
lzma_file_input_callback,
|
||||
( void * )&ctx,
|
||||
lzma_file_output_callback,
|
||||
( void * )&ctx,
|
||||
NULL,
|
||||
NULL );
|
||||
|
||||
elzma_compress_free( &handle );
|
||||
FC_ASSERT( rc == ELZMA_E_OK );
|
||||
}
|
||||
|
||||
void lzma_decompress_file( const path& src_path,
|
||||
const path& dst_path )
|
||||
{
|
||||
FC_ASSERT( exists( src_path ) );
|
||||
FC_ASSERT( !exists( dst_path ) );
|
||||
|
||||
boost::iostreams::mapped_file_source src_file;
|
||||
src_file.open( src_path.string() );
|
||||
FC_ASSERT( src_file.is_open() );
|
||||
|
||||
elzma_decompress_handle handle = NULL;
|
||||
handle = elzma_decompress_alloc();
|
||||
FC_ASSERT( handle != NULL );
|
||||
|
||||
struct lzma_file_ctx ctx;
|
||||
ctx.src_buf = ( const unsigned char* )src_file.data();
|
||||
ctx.src_len = src_file.size();
|
||||
ctx.dst_path = dst_path;
|
||||
|
||||
auto rc = elzma_decompress_run( handle,
|
||||
lzma_file_input_callback,
|
||||
( void * )&ctx,
|
||||
lzma_file_output_callback,
|
||||
( void * )&ctx,
|
||||
elzma_file_format::ELZMA_lzma );
|
||||
|
||||
elzma_decompress_free( &handle );
|
||||
FC_ASSERT( rc == ELZMA_E_OK );
|
||||
}
|
||||
|
||||
} // namespace fc
|
||||
|
|
|
|||
|
|
@ -8,6 +8,18 @@
|
|||
|
||||
#include <fc/log/logger.hpp>
|
||||
|
||||
#include <fc/thread/thread.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <openssl/opensslconf.h>
|
||||
#ifndef OPENSSL_THREADS
|
||||
# error "OpenSSL must be configured to support threads"
|
||||
#endif
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# include <Windows.h>
|
||||
#endif
|
||||
|
||||
namespace fc {
|
||||
|
||||
struct aes_encoder::impl
|
||||
|
|
@ -157,13 +169,13 @@ uint32_t aes_decoder::final_decode( char* plaintext )
|
|||
|
||||
|
||||
/** example method from wiki.opensslfoundation.com */
|
||||
int aes_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
|
||||
unsigned char *iv, unsigned char *ciphertext)
|
||||
unsigned aes_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
|
||||
unsigned char *iv, unsigned char *ciphertext)
|
||||
{
|
||||
evp_cipher_ctx ctx( EVP_CIPHER_CTX_new() );
|
||||
|
||||
int len = 0;
|
||||
int ciphertext_len = 0;
|
||||
unsigned ciphertext_len = 0;
|
||||
|
||||
/* Create and initialise the context */
|
||||
if(!ctx)
|
||||
|
|
@ -206,12 +218,12 @@ int aes_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
|
|||
return ciphertext_len;
|
||||
}
|
||||
|
||||
int aes_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
|
||||
unsigned char *iv, unsigned char *plaintext)
|
||||
unsigned aes_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
|
||||
unsigned char *iv, unsigned char *plaintext)
|
||||
{
|
||||
evp_cipher_ctx ctx( EVP_CIPHER_CTX_new() );
|
||||
int len = 0;
|
||||
int plaintext_len = 0;
|
||||
unsigned plaintext_len = 0;
|
||||
|
||||
/* Create and initialise the context */
|
||||
if(!ctx)
|
||||
|
|
@ -255,12 +267,12 @@ int aes_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *ke
|
|||
return plaintext_len;
|
||||
}
|
||||
|
||||
int aes_cfb_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
|
||||
unsigned char *iv, unsigned char *plaintext)
|
||||
unsigned aes_cfb_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key,
|
||||
unsigned char *iv, unsigned char *plaintext)
|
||||
{
|
||||
evp_cipher_ctx ctx( EVP_CIPHER_CTX_new() );
|
||||
int len = 0;
|
||||
int plaintext_len = 0;
|
||||
unsigned plaintext_len = 0;
|
||||
|
||||
/* Create and initialise the context */
|
||||
if(!ctx)
|
||||
|
|
@ -308,8 +320,8 @@ std::vector<char> aes_encrypt( const fc::sha512& key, const std::vector<char>& p
|
|||
{
|
||||
std::vector<char> cipher_text(plain_text.size()+16);
|
||||
auto cipher_len = aes_encrypt( (unsigned char*)plain_text.data(), plain_text.size(),
|
||||
(unsigned char*)&key, ((unsigned char*)&key)+32,
|
||||
(unsigned char*)cipher_text.data() );
|
||||
(unsigned char*)&key, ((unsigned char*)&key)+32,
|
||||
(unsigned char*)cipher_text.data() );
|
||||
FC_ASSERT( cipher_len <= cipher_text.size() );
|
||||
cipher_text.resize(cipher_len);
|
||||
return cipher_text;
|
||||
|
|
@ -365,4 +377,63 @@ std::vector<char> aes_load( const fc::path& file, const fc::sha512& key )
|
|||
return aes_decrypt( key, cipher );
|
||||
} FC_RETHROW_EXCEPTIONS( warn, "", ("file",file) ) }
|
||||
|
||||
/* This stuff has to go somewhere, I guess this is as good a place as any...
|
||||
OpenSSL isn't thread-safe unless you give it access to some mutexes,
|
||||
so the CRYPTO_set_id_callback() function needs to be called before there's any
|
||||
chance of OpenSSL being accessed from multiple threads.
|
||||
*/
|
||||
struct openssl_thread_config
|
||||
{
|
||||
static boost::mutex* openssl_mutexes;
|
||||
static unsigned long get_thread_id();
|
||||
static void locking_callback(int mode, int type, const char *file, int line);
|
||||
openssl_thread_config();
|
||||
~openssl_thread_config();
|
||||
};
|
||||
openssl_thread_config openssl_thread_config_manager;
|
||||
|
||||
boost::mutex* openssl_thread_config::openssl_mutexes = nullptr;
|
||||
|
||||
unsigned long openssl_thread_config::get_thread_id()
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return (unsigned long)::GetCurrentThreadId();
|
||||
#else
|
||||
return (unsigned long)(&fc::thread::current()); // TODO: should expose boost thread id
|
||||
#endif
|
||||
}
|
||||
|
||||
void openssl_thread_config::locking_callback(int mode, int type, const char *file, int line)
|
||||
{
|
||||
if (mode & CRYPTO_LOCK)
|
||||
openssl_mutexes[type].lock();
|
||||
else
|
||||
openssl_mutexes[type].unlock();
|
||||
}
|
||||
|
||||
// Warning: Things get complicated if third-party libraries also try to install their their own
|
||||
// OpenSSL thread functions. Right now, we don't install our own handlers if another library has
|
||||
// installed them before us which is a partial solution, but you'd really need to evaluate
|
||||
// each library that does this to make sure they will play nice.
|
||||
openssl_thread_config::openssl_thread_config()
|
||||
{
|
||||
if (CRYPTO_get_id_callback() == NULL &&
|
||||
CRYPTO_get_locking_callback() == NULL)
|
||||
{
|
||||
openssl_mutexes = new boost::mutex[CRYPTO_num_locks()];
|
||||
CRYPTO_set_id_callback(&get_thread_id);
|
||||
CRYPTO_set_locking_callback(&locking_callback);
|
||||
}
|
||||
}
|
||||
openssl_thread_config::~openssl_thread_config()
|
||||
{
|
||||
if (CRYPTO_get_id_callback() == &get_thread_id)
|
||||
{
|
||||
CRYPTO_set_id_callback(NULL);
|
||||
CRYPTO_set_locking_callback(NULL);
|
||||
delete[] openssl_mutexes;
|
||||
openssl_mutexes = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace fc
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ namespace fc { namespace ecc {
|
|||
std::string public_key::to_base58() const
|
||||
{
|
||||
public_key_data key = serialize();
|
||||
uint32_t check = sha256::hash(key.data, sizeof(key))._hash[0];
|
||||
uint32_t check = (uint32_t)sha256::hash(key.data, sizeof(key))._hash[0];
|
||||
assert(key.size() + sizeof(check) == 37);
|
||||
array<char, 37> data;
|
||||
memcpy(data.data, key.begin(), key.size());
|
||||
|
|
@ -280,7 +280,7 @@ namespace fc { namespace ecc {
|
|||
FC_ASSERT( s == sizeof(data) );
|
||||
|
||||
public_key_data key;
|
||||
uint32_t check = sha256::hash(data.data, sizeof(key))._hash[0];
|
||||
uint32_t check = (uint32_t)sha256::hash(data.data, sizeof(key))._hash[0];
|
||||
FC_ASSERT( memcmp( (char*)&check, data.data + sizeof(key), sizeof(check) ) == 0 );
|
||||
memcpy( (char*)key.data, data.data, sizeof(key) );
|
||||
return public_key(key);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
namespace fc
|
||||
{
|
||||
romix::romix( u_int32_t memReqts, u_int32_t numIter, std::string salt ) :
|
||||
romix::romix( uint32_t memReqts, uint32_t numIter, std::string salt ) :
|
||||
hashOutputBytes_( 64 ),
|
||||
kdfOutputBytes_( 32 )
|
||||
{
|
||||
|
|
@ -32,7 +32,7 @@ namespace fc
|
|||
|
||||
// Prepare the lookup table
|
||||
char *lookupTable_ = new char[memoryReqtBytes_];
|
||||
u_int32_t const HSZ = hashOutputBytes_;
|
||||
uint32_t const HSZ = hashOutputBytes_;
|
||||
|
||||
// First hash to seed the lookup table, input is variable length anyway
|
||||
fc::sha512 hash = sha512.hash(saltedPassword);
|
||||
|
|
@ -40,7 +40,7 @@ namespace fc
|
|||
|
||||
// Compute <sequenceCount_> consecutive hashes of the passphrase
|
||||
// Every iteration is stored in the next 64-bytes in the Lookup table
|
||||
for( u_int32_t nByte = 0; nByte < memoryReqtBytes_ - HSZ; nByte += HSZ )
|
||||
for( uint32_t nByte = 0; nByte < memoryReqtBytes_ - HSZ; nByte += HSZ )
|
||||
{
|
||||
// Compute hash of slot i, put result in slot i+1
|
||||
fc::sha512 hash = sha512.hash(lookupTable_ + nByte, HSZ);
|
||||
|
|
@ -54,11 +54,11 @@ namespace fc
|
|||
|
||||
// We "integerize" a hash value by taking the last 4 bytes of
|
||||
// as a u_int32_t, and take modulo sequenceCount
|
||||
u_int64_t* X64ptr = (u_int64_t*)(X.data());
|
||||
u_int64_t* Y64ptr = (u_int64_t*)(Y.data());
|
||||
u_int64_t* V64ptr = NULL;
|
||||
u_int32_t newIndex;
|
||||
u_int32_t const nXorOps = HSZ / sizeof(u_int64_t);
|
||||
uint64_t* X64ptr = (uint64_t*)(X.data());
|
||||
uint64_t* Y64ptr = (uint64_t*)(Y.data());
|
||||
uint64_t* V64ptr = NULL;
|
||||
uint32_t newIndex;
|
||||
uint32_t const nXorOps = HSZ / sizeof(uint64_t);
|
||||
|
||||
// Pure ROMix would use sequenceCount_ for the number of lookups.
|
||||
// We divide by 2 to reduce computation time RELATIVE to the memory usage
|
||||
|
|
@ -66,17 +66,17 @@ namespace fc
|
|||
// memory in the same amount of time (and this is the justification for
|
||||
// the scrypt algorithm -- it is basically ROMix, modified for more
|
||||
// flexibility in controlling compute-time vs memory-usage).
|
||||
u_int32_t const nLookups = sequenceCount_ / 2;
|
||||
for(u_int32_t nSeq=0; nSeq<nLookups; nSeq++)
|
||||
uint32_t const nLookups = sequenceCount_ / 2;
|
||||
for(uint32_t nSeq=0; nSeq<nLookups; nSeq++)
|
||||
{
|
||||
// Interpret last 4 bytes of last result (mod seqCt) as next LUT index
|
||||
newIndex = *(u_int32_t*)(X.data()+HSZ-4) % sequenceCount_;
|
||||
newIndex = *(uint32_t*)(X.data()+HSZ-4) % sequenceCount_;
|
||||
|
||||
// V represents the hash result at <newIndex>
|
||||
V64ptr = (u_int64_t*)(lookupTable_ + HSZ * newIndex);
|
||||
V64ptr = (uint64_t*)(lookupTable_ + HSZ * newIndex);
|
||||
|
||||
// xor X with V, and store the result in X
|
||||
for(u_int32_t i = 0; i < nXorOps; i++)
|
||||
for(uint32_t i = 0; i < nXorOps; i++)
|
||||
*(Y64ptr + i) = *(X64ptr + i) ^ *(V64ptr + i);
|
||||
|
||||
// Hash the xor'd data to get the next index for lookup
|
||||
|
|
@ -91,7 +91,7 @@ namespace fc
|
|||
std::string romix::deriveKey( std::string const & password )
|
||||
{
|
||||
std::string masterKey(password);
|
||||
for(u_int32_t i=0; i<numIterations_; i++)
|
||||
for(uint32_t i=0; i<numIterations_; i++)
|
||||
masterKey = deriveKey_OneIter(masterKey);
|
||||
|
||||
return masterKey;
|
||||
|
|
|
|||
|
|
@ -1,57 +1,22 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include <fc/crypto/openssl.hpp>
|
||||
#include <fc/crypto/scrypt.hpp>
|
||||
#include <fc/exception/exception.hpp>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#define SCRYPT_SALSA 1
|
||||
#define SCRYPT_SHA256 1
|
||||
|
||||
/*
|
||||
#include "code/scrypt-jane-portable.h"
|
||||
#include "code/scrypt-jane-romix.h"
|
||||
*/
|
||||
#include "scrypt-jane.h"
|
||||
|
||||
namespace fc {
|
||||
|
||||
void scrypt_derive_key( const std::vector<unsigned char> &passphrase, const std::vector<unsigned char> &salt,
|
||||
unsigned int n, unsigned int r, unsigned int p, std::vector<unsigned char> &key )
|
||||
{
|
||||
/*
|
||||
unsigned int chunk_bytes = SCRYPT_BLOCK_BYTES * r * 2;
|
||||
std::vector<unsigned char> yx((p+1) * chunk_bytes);
|
||||
unsigned log2( unsigned n )
|
||||
{
|
||||
if( n <= 0 ) FC_THROW_EXCEPTION( exception, "cannot take log2(${n})", ("n",n) );
|
||||
unsigned i = 0;
|
||||
while( n >>= 1 ) ++i;
|
||||
return i;
|
||||
}
|
||||
|
||||
unsigned char *Y = &yx[0];
|
||||
unsigned char *X = &yx[chunk_bytes];
|
||||
|
||||
if(PKCS5_PBKDF2_HMAC( (const char*)&passphrase[0], passphrase.size(),
|
||||
&salt[0], salt.size(), 1,
|
||||
EVP_sha256(), chunk_bytes * p, X) != 1 )
|
||||
{
|
||||
std::fill( yx.begin(), yx.end(), 0 );
|
||||
FC_THROW_EXCEPTION( exception, "error generating key material",
|
||||
("s", ERR_error_string( ERR_get_error(), nullptr) ) );
|
||||
}
|
||||
|
||||
std::vector<unsigned char> v(n * chunk_bytes);
|
||||
|
||||
for( unsigned int i = 0; i < p; i++ )
|
||||
scrypt_ROMix_basic( (uint32_t*)(X+(chunk_bytes*i)), (uint32_t*)Y, (uint32_t*)&v[0], n, r );
|
||||
|
||||
if(PKCS5_PBKDF2_HMAC( (const char*)&passphrase[0], passphrase.size(),
|
||||
X, chunk_bytes * p, 1,
|
||||
EVP_sha256(), key.size(), &key[0]) != 1 )
|
||||
{
|
||||
std::fill( yx.begin(), yx.end(), 0 );
|
||||
std::fill( v.begin(), v.end(), 0 );
|
||||
FC_THROW_EXCEPTION( exception, "error generating key material",
|
||||
("s", ERR_error_string( ERR_get_error(), nullptr) ) );
|
||||
}
|
||||
|
||||
std::fill( yx.begin(), yx.end(), 0 );
|
||||
std::fill( v.begin(), v.end(), 0 );
|
||||
*/
|
||||
}
|
||||
void scrypt_derive_key( const std::vector<unsigned char>& passphrase, const std::vector<unsigned char>& salt,
|
||||
unsigned int n, unsigned int r, unsigned int p, std::vector<unsigned char>& key )
|
||||
{
|
||||
scrypt( passphrase.data(), passphrase.size(), salt.data(), salt.size(),
|
||||
log2( n ) - 1, log2( r ), log2( p ), key.data(), key.capacity() );
|
||||
}
|
||||
|
||||
} // namespace fc
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ namespace fc
|
|||
string exception::to_string( log_level ll )const
|
||||
{
|
||||
fc::stringstream ss;
|
||||
ss << what() << "(" << variant(my->_code).as_string() <<")\n";
|
||||
ss << what() << " (" << variant(my->_code).as_string() <<")\n";
|
||||
for( auto itr = my->_elog.begin(); itr != my->_elog.end(); ++itr )
|
||||
{
|
||||
ss << fc::format_string( itr->get_format(), itr->get_data() ) <<"\n";
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ process::~process(){}
|
|||
|
||||
iprocess& process::exec( const fc::path& exe,
|
||||
std::vector<std::string> args,
|
||||
const fc::path& work_dir, exec_opts opt )
|
||||
const fc::path& work_dir, int opt )
|
||||
{
|
||||
|
||||
my->pctx.work_dir = work_dir.string();
|
||||
|
|
|
|||
|
|
@ -1,36 +1,181 @@
|
|||
#include <fc/log/file_appender.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <fc/thread/scoped_lock.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <fc/compress/lzma.hpp>
|
||||
#include <fc/exception/exception.hpp>
|
||||
#include <fc/io/fstream.hpp>
|
||||
#include <fc/variant.hpp>
|
||||
#include <fc/log/file_appender.hpp>
|
||||
#include <fc/reflect/variant.hpp>
|
||||
#include <fc/thread/scoped_lock.hpp>
|
||||
#include <fc/thread/thread.hpp>
|
||||
#include <fc/variant.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
#include <iomanip>
|
||||
#include <queue>
|
||||
#include <sstream>
|
||||
#include <fc/filesystem.hpp>
|
||||
|
||||
|
||||
namespace fc {
|
||||
|
||||
static const string compression_extension( ".lzma" );
|
||||
|
||||
class file_appender::impl : public fc::retainable {
|
||||
public:
|
||||
config cfg;
|
||||
ofstream out;
|
||||
boost::mutex slock;
|
||||
config cfg;
|
||||
ofstream out;
|
||||
boost::mutex slock;
|
||||
|
||||
private:
|
||||
future<void> _rotation_task;
|
||||
time_point_sec _current_file_start_time;
|
||||
std::unique_ptr<thread> _compression_thread;
|
||||
|
||||
time_point_sec get_file_start_time( const time_point_sec& timestamp, const microseconds& interval )
|
||||
{
|
||||
const auto interval_seconds = interval.to_seconds();
|
||||
const auto file_number = timestamp.sec_since_epoch() / interval_seconds;
|
||||
return time_point_sec( file_number * interval_seconds );
|
||||
}
|
||||
|
||||
string timestamp_to_string( const time_point_sec& timestamp )
|
||||
{
|
||||
auto ptime = boost::posix_time::from_time_t( time_t ( timestamp.sec_since_epoch() ) );
|
||||
return boost::posix_time::to_iso_string( ptime );
|
||||
}
|
||||
|
||||
time_point_sec string_to_timestamp( const string& str )
|
||||
{
|
||||
return time_point::from_iso_string( str );
|
||||
}
|
||||
|
||||
void compress_file( const string& filename )
|
||||
{
|
||||
FC_ASSERT( cfg.rotate && cfg.rotation_compression );
|
||||
FC_ASSERT( _compression_thread );
|
||||
if( !_compression_thread->is_current() )
|
||||
{
|
||||
_compression_thread->async( [this, filename]() { compress_file( filename ); } ).wait();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
lzma_compress_file( filename, filename + compression_extension );
|
||||
remove_all( filename );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
impl( const config& c) : cfg( c )
|
||||
{
|
||||
if( cfg.rotate )
|
||||
{
|
||||
FC_ASSERT( cfg.rotation_interval >= seconds( 1 ) );
|
||||
FC_ASSERT( cfg.rotation_limit >= cfg.rotation_interval );
|
||||
|
||||
if( cfg.rotation_compression )
|
||||
_compression_thread.reset( new thread( "compression") );
|
||||
|
||||
_rotation_task = async( [this]() { rotate_files( true ); } );
|
||||
}
|
||||
}
|
||||
|
||||
~impl()
|
||||
{
|
||||
try
|
||||
{
|
||||
_rotation_task.cancel_and_wait();
|
||||
if( _compression_thread ) _compression_thread->quit();
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void rotate_files( bool initializing = false )
|
||||
{
|
||||
FC_ASSERT( cfg.rotate );
|
||||
const auto now = time_point::now();
|
||||
const auto start_time = get_file_start_time( now, cfg.rotation_interval );
|
||||
const auto timestamp_string = timestamp_to_string( start_time );
|
||||
const auto link_filename = cfg.filename.string();
|
||||
const auto log_filename = link_filename + "." + timestamp_string;
|
||||
|
||||
{
|
||||
fc::scoped_lock<boost::mutex> lock( slock );
|
||||
|
||||
if( !initializing )
|
||||
{
|
||||
if( start_time <= _current_file_start_time )
|
||||
{
|
||||
_rotation_task = schedule( [this]() { rotate_files(); }, _current_file_start_time + cfg.rotation_interval.to_seconds() );
|
||||
return;
|
||||
}
|
||||
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
|
||||
out.open( log_filename.c_str() );
|
||||
}
|
||||
remove_all( link_filename );
|
||||
create_hard_link( log_filename, link_filename );
|
||||
|
||||
/* Delete old log files */
|
||||
const auto limit_time = now - cfg.rotation_limit;
|
||||
auto itr = directory_iterator( fc::path( link_filename ).parent_path() );
|
||||
for( ; itr != directory_iterator(); itr++ )
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto current_filename = itr->string();
|
||||
auto current_pos = current_filename.find( link_filename );
|
||||
if( current_pos != 0 ) continue;
|
||||
current_pos = link_filename.size() + 1;
|
||||
const auto current_timestamp_str = string( current_filename.begin() + current_pos, /* substr not working */
|
||||
current_filename.begin() + current_pos + timestamp_string.size() );
|
||||
const auto current_timestamp = string_to_timestamp( current_timestamp_str );
|
||||
if( current_timestamp < start_time )
|
||||
{
|
||||
if( current_timestamp < limit_time || file_size( current_filename ) <= 0 )
|
||||
{
|
||||
remove_all( current_filename );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !cfg.rotation_compression ) continue;
|
||||
if( current_filename.find( compression_extension ) != string::npos ) continue;
|
||||
compress_file( current_filename );
|
||||
}
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
_current_file_start_time = start_time;
|
||||
_rotation_task = schedule( [this]() { rotate_files(); }, _current_file_start_time + cfg.rotation_interval.to_seconds() );
|
||||
}
|
||||
};
|
||||
file_appender::config::config( const fc::path& p )
|
||||
:format( "${timestamp} ${thread_name} ${context} ${file}:${line} ${method} ${level}] ${message}" ),
|
||||
filename(p),flush(true),truncate(true){}
|
||||
filename(p),flush(true),truncate(true),rotate(false),rotation_compression(true){}
|
||||
|
||||
file_appender::file_appender( const variant& args )
|
||||
:my( new impl() )
|
||||
:my( new impl( args.as<config>() ) )
|
||||
{
|
||||
try {
|
||||
my->cfg = args.as<config>();
|
||||
fc::create_directories( fc::path( my->cfg.filename.string() ).parent_path() );
|
||||
my->out.open( my->cfg.filename.string().c_str() );
|
||||
} catch ( ... ) {
|
||||
std::cerr << "error opening log file: " << my->cfg.filename.string() << "\n";
|
||||
//elog( "%s", fc::except_str().c_str() );
|
||||
std::string log_filename;
|
||||
try
|
||||
{
|
||||
log_filename = my->cfg.filename.string();
|
||||
|
||||
fc::create_directories( fc::path( log_filename ).parent_path() );
|
||||
|
||||
if( !my->cfg.rotate ) my->out.open( log_filename.c_str() );
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
std::cerr << "error opening log file: " << log_filename << "\n";
|
||||
}
|
||||
}
|
||||
file_appender::~file_appender(){}
|
||||
|
|
@ -60,14 +205,15 @@ namespace fc {
|
|||
fc::string message = fc::format_string( m.get_format(), m.get_data() );
|
||||
line << message.c_str();
|
||||
|
||||
|
||||
//fc::variant lmsg(m);
|
||||
|
||||
// fc::string fmt_str = fc::format_string( my->cfg.format, mutable_variant_object(m.get_context())( "message", message) );
|
||||
// fc::string fmt_str = fc::format_string( my->cfg.format, mutable_variant_object(m.get_context())( "message", message) );
|
||||
|
||||
{
|
||||
fc::scoped_lock<boost::mutex> lock(my->slock);
|
||||
fc::scoped_lock<boost::mutex> lock( my->slock );
|
||||
my->out << line.str() << "\t\t\t" << m.get_context().get_file() <<":"<<m.get_context().get_line_number()<<"\n";
|
||||
if( my->cfg.flush ) my->out.flush();
|
||||
}
|
||||
if( my->cfg.flush ) my->out.flush();
|
||||
}
|
||||
}
|
||||
|
||||
} // fc
|
||||
|
|
|
|||
|
|
@ -16,20 +16,19 @@ namespace fc
|
|||
class ntp_impl
|
||||
{
|
||||
public:
|
||||
ntp_impl() :_request_interval_sec( 60*60 /* 1 hr */)
|
||||
ntp_impl():_request_interval_sec( 60*60 /* 1 hr */),_ntp_thread("ntp")
|
||||
{
|
||||
_next_request_time = fc::time_point::now();
|
||||
_ntp_hosts.push_back( std::make_pair( "pool.ntp.org",123 ) );
|
||||
}
|
||||
|
||||
/** vector < host, port > */
|
||||
std::vector< std::pair< std::string, uint16_t> > _ntp_hosts;
|
||||
fc::future<void> _request_loop;
|
||||
fc::future<void> _read_loop;
|
||||
udp_socket _sock;
|
||||
uint32_t _request_interval_sec;
|
||||
fc::time_point _next_request_time;
|
||||
fc::time_point _last_request_time;
|
||||
optional<fc::microseconds> _last_ntp_delta;
|
||||
fc::thread _ntp_thread;
|
||||
|
||||
void request_now()
|
||||
{
|
||||
|
|
@ -43,6 +42,7 @@ namespace fc
|
|||
{
|
||||
ilog( "sending request to ${ep}", ("ep",ep) );
|
||||
std::array<unsigned char, 48> send_buf { {010,0,0,0,0,0,0,0,0} };
|
||||
_last_request_time = fc::time_point::now();
|
||||
_sock.send_to( (const char*)send_buf.data(), send_buf.size(), ep );
|
||||
break;
|
||||
}
|
||||
|
|
@ -55,17 +55,10 @@ namespace fc
|
|||
}
|
||||
} // request_now
|
||||
|
||||
void request_loop()
|
||||
void request_time()
|
||||
{
|
||||
while( !_request_loop.canceled() )
|
||||
{
|
||||
if( _next_request_time < fc::time_point::now() )
|
||||
{
|
||||
_next_request_time += fc::seconds( _request_interval_sec );
|
||||
request_now();
|
||||
}
|
||||
fc::usleep( fc::seconds(1) ); // TODO: fix FC timers..
|
||||
} // while
|
||||
request_now();
|
||||
_ntp_thread.schedule( [=](){ request_time(); }, fc::time_point::now() + fc::seconds(_request_interval_sec) );
|
||||
} // request_loop
|
||||
|
||||
void read_loop()
|
||||
|
|
@ -86,14 +79,19 @@ namespace fc
|
|||
uint32_t seconds_since_1900 = receive_timestamp_host >> 32;
|
||||
uint32_t seconds_since_epoch = seconds_since_1900 - 2208988800;
|
||||
|
||||
auto ntp_time = (fc::time_point() + fc::seconds(seconds_since_epoch) + fc::microseconds(microseconds));
|
||||
if( ntp_time - fc::time_point::now() < fc::seconds(60*60*24) &&
|
||||
fc::time_point::now() - ntp_time < fc::seconds(60*60*24) )
|
||||
{
|
||||
_last_ntp_delta = ntp_time - fc::time_point::now();
|
||||
}
|
||||
if( fc::time_point::now() - _last_request_time > fc::seconds(1) )
|
||||
request_now();
|
||||
else
|
||||
elog( "NTP time is way off ${time}", ("time",ntp_time)("local",fc::time_point::now()) );
|
||||
{
|
||||
auto ntp_time = (fc::time_point() + fc::seconds(seconds_since_epoch) + fc::microseconds(microseconds));
|
||||
if( ntp_time - fc::time_point::now() < fc::seconds(60*60*24) &&
|
||||
fc::time_point::now() - ntp_time < fc::seconds(60*60*24) )
|
||||
{
|
||||
_last_ntp_delta = ntp_time - fc::time_point::now();
|
||||
}
|
||||
else
|
||||
elog( "NTP time is way off ${time}", ("time",ntp_time)("local",fc::time_point::now()) );
|
||||
}
|
||||
}
|
||||
} // read_loop
|
||||
};
|
||||
|
|
@ -108,17 +106,15 @@ namespace fc
|
|||
{
|
||||
my->_sock.open();
|
||||
|
||||
my->_request_loop = fc::async( [=](){ my->request_loop(); } );
|
||||
my->_read_loop = fc::async( [=](){ my->read_loop(); } );
|
||||
my->_ntp_thread.async( [=](){ my->request_time(); } );
|
||||
my->_read_loop = my->_ntp_thread.async( [=](){ my->read_loop(); } );
|
||||
}
|
||||
|
||||
ntp::~ntp()
|
||||
{
|
||||
try {
|
||||
my->_request_loop.cancel();
|
||||
my->_read_loop.cancel();
|
||||
my->_sock.close();
|
||||
my->_request_loop.wait();
|
||||
my->_read_loop.wait();
|
||||
}
|
||||
catch ( const fc::exception& )
|
||||
|
|
@ -137,8 +133,8 @@ namespace fc
|
|||
void ntp::set_request_interval( uint32_t interval_sec )
|
||||
{
|
||||
my->_request_interval_sec = interval_sec;
|
||||
my->_next_request_time = fc::time_point::now();
|
||||
}
|
||||
|
||||
void ntp::request_now()
|
||||
{
|
||||
my->request_now();
|
||||
|
|
|
|||
|
|
@ -23,21 +23,25 @@ namespace fc {
|
|||
{
|
||||
if( _sock.is_open() )
|
||||
_sock.close();
|
||||
if( _read_in_progress.valid() ) try { _read_in_progress.wait(); } catch ( ... ) {}
|
||||
if( _write_in_progress.valid() ) try { _write_in_progress.wait(); } catch ( ... ) {}
|
||||
}
|
||||
virtual size_t readsome(boost::asio::ip::tcp::socket& socket, char* buffer, size_t length) override;
|
||||
virtual size_t writesome(boost::asio::ip::tcp::socket& socket, const char* buffer, size_t length) override;
|
||||
|
||||
fc::future<size_t> _write_in_progress;
|
||||
fc::future<size_t> _read_in_progress;
|
||||
boost::asio::ip::tcp::socket _sock;
|
||||
tcp_socket_io_hooks* _io_hooks;
|
||||
};
|
||||
|
||||
size_t tcp_socket::impl::readsome(boost::asio::ip::tcp::socket& socket, char* buffer, size_t length)
|
||||
{
|
||||
return fc::asio::read_some(socket, boost::asio::buffer(buffer, length));
|
||||
return (_read_in_progress = fc::asio::read_some(socket, boost::asio::buffer(buffer, length))).wait();
|
||||
}
|
||||
size_t tcp_socket::impl::writesome(boost::asio::ip::tcp::socket& socket, const char* buffer, size_t length)
|
||||
{
|
||||
return fc::asio::write_some(socket, boost::asio::buffer(buffer, length));
|
||||
return (_write_in_progress = fc::asio::write_some(socket, boost::asio::buffer(buffer, length))).wait();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
395
src/network/udt_socket.cpp
Normal file
395
src/network/udt_socket.cpp
Normal file
|
|
@ -0,0 +1,395 @@
|
|||
#include <fc/network/udt_socket.hpp>
|
||||
#include <fc/thread/thread.hpp>
|
||||
#include <fc/thread/mutex.hpp>
|
||||
#include <fc/thread/unique_lock.hpp>
|
||||
#include <fc/network/ip.hpp>
|
||||
#include <udt.h>
|
||||
|
||||
#ifndef WIN32
|
||||
# include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
namespace fc {
|
||||
|
||||
void check_udt_errors()
|
||||
{
|
||||
UDT::ERRORINFO& error_info = UDT::getlasterror();
|
||||
if( error_info.getErrorCode() )
|
||||
{
|
||||
std::string error_message = error_info.getErrorMessage();
|
||||
error_info.clear();
|
||||
FC_CAPTURE_AND_THROW( udt_exception, (error_message) );
|
||||
}
|
||||
}
|
||||
|
||||
class udt_epoll_service
|
||||
{
|
||||
public:
|
||||
udt_epoll_service()
|
||||
:_epoll_thread("udt_epoll")
|
||||
{
|
||||
UDT::startup();
|
||||
check_udt_errors();
|
||||
_epoll_id = UDT::epoll_create();
|
||||
_epoll_loop = _epoll_thread.async( [=](){ poll_loop(); } );
|
||||
}
|
||||
|
||||
~udt_epoll_service()
|
||||
{
|
||||
_epoll_loop.cancel();
|
||||
_epoll_loop.wait();
|
||||
UDT::cleanup();
|
||||
}
|
||||
|
||||
void poll_loop()
|
||||
{
|
||||
std::set<UDTSOCKET> read_ready;
|
||||
std::set<UDTSOCKET> write_ready;
|
||||
while( !_epoll_loop.canceled() )
|
||||
{
|
||||
UDT::epoll_wait( _epoll_id,
|
||||
&read_ready,
|
||||
&write_ready, 100000000 );
|
||||
|
||||
{ synchronized(_read_promises_mutex)
|
||||
for( auto sock : read_ready )
|
||||
{
|
||||
auto itr = _read_promises.find( sock );
|
||||
if( itr != _read_promises.end() )
|
||||
{
|
||||
itr->second->set_value();
|
||||
_read_promises.erase(itr);
|
||||
}
|
||||
}
|
||||
} // synchronized read promise mutex
|
||||
|
||||
{ synchronized(_write_promises_mutex)
|
||||
for( auto sock : write_ready )
|
||||
{
|
||||
auto itr = _write_promises.find( sock );
|
||||
if( itr != _write_promises.end() )
|
||||
{
|
||||
itr->second->set_value();
|
||||
_write_promises.erase(itr);
|
||||
}
|
||||
}
|
||||
} // synchronized write promise mutex
|
||||
} // while not canceled
|
||||
} // poll_loop
|
||||
|
||||
|
||||
void notify_read( int udt_socket_id,
|
||||
const promise<void>::ptr& p )
|
||||
{
|
||||
int events = UDT_EPOLL_IN | UDT_EPOLL_ERR;
|
||||
if( 0 != UDT::epoll_add_usock( _epoll_id,
|
||||
udt_socket_id,
|
||||
&events ) )
|
||||
{
|
||||
check_udt_errors();
|
||||
}
|
||||
{ synchronized(_read_promises_mutex)
|
||||
|
||||
_read_promises[udt_socket_id] = p;
|
||||
}
|
||||
}
|
||||
|
||||
void notify_write( int udt_socket_id,
|
||||
const promise<void>::ptr& p )
|
||||
{
|
||||
int events = UDT_EPOLL_OUT | UDT_EPOLL_ERR;
|
||||
if( 0 != UDT::epoll_add_usock( _epoll_id,
|
||||
udt_socket_id,
|
||||
&events ) )
|
||||
{
|
||||
check_udt_errors();
|
||||
}
|
||||
|
||||
{ synchronized(_write_promises_mutex)
|
||||
_write_promises[udt_socket_id] = p;
|
||||
}
|
||||
}
|
||||
void remove( int udt_socket_id )
|
||||
{
|
||||
{ synchronized(_read_promises_mutex)
|
||||
auto read_itr = _read_promises.find( udt_socket_id );
|
||||
if( read_itr != _read_promises.end() )
|
||||
{
|
||||
read_itr->second->set_exception( fc::copy_exception( fc::canceled_exception() ) );
|
||||
_read_promises.erase(read_itr);
|
||||
}
|
||||
}
|
||||
{ synchronized(_write_promises_mutex)
|
||||
auto write_itr = _write_promises.find( udt_socket_id );
|
||||
if( write_itr != _write_promises.end() )
|
||||
{
|
||||
write_itr->second->set_exception( fc::copy_exception( fc::canceled_exception() ) );
|
||||
_write_promises.erase(write_itr);
|
||||
}
|
||||
}
|
||||
UDT::epoll_remove_usock( _epoll_id, udt_socket_id );
|
||||
}
|
||||
|
||||
private:
|
||||
fc::mutex _read_promises_mutex;
|
||||
fc::mutex _write_promises_mutex;
|
||||
std::unordered_map<int, promise<void>::ptr > _read_promises;
|
||||
std::unordered_map<int, promise<void>::ptr > _write_promises;
|
||||
|
||||
fc::future<void> _epoll_loop;
|
||||
fc::thread _epoll_thread;
|
||||
int _epoll_id;
|
||||
};
|
||||
|
||||
|
||||
udt_epoll_service& default_epool_service()
|
||||
{
|
||||
static udt_epoll_service* default_service = new udt_epoll_service();
|
||||
return *default_service;
|
||||
}
|
||||
|
||||
|
||||
|
||||
udt_socket::udt_socket()
|
||||
:_udt_socket_id( UDT::INVALID_SOCK )
|
||||
{
|
||||
}
|
||||
|
||||
udt_socket::~udt_socket()
|
||||
{
|
||||
try {
|
||||
close();
|
||||
} catch ( const fc::exception& e )
|
||||
{
|
||||
wlog( "${e}", ("e", e.to_detail_string() ) );
|
||||
}
|
||||
}
|
||||
|
||||
void udt_socket::bind( const fc::ip::endpoint& local_endpoint )
|
||||
{ try {
|
||||
if( !is_open() )
|
||||
open();
|
||||
|
||||
sockaddr_in local_addr;
|
||||
local_addr.sin_family = AF_INET;
|
||||
local_addr.sin_port = htons(local_endpoint.port());
|
||||
local_addr.sin_addr.s_addr = htonl(local_endpoint.get_address());
|
||||
|
||||
if( UDT::ERROR == UDT::bind(_udt_socket_id, (sockaddr*)&local_addr, sizeof(local_addr)) )
|
||||
check_udt_errors();
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
void udt_socket::connect_to( const ip::endpoint& remote_endpoint )
|
||||
{ try {
|
||||
if( !is_open() )
|
||||
open();
|
||||
|
||||
sockaddr_in serv_addr;
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_port = htons(remote_endpoint.port());
|
||||
serv_addr.sin_addr.s_addr = htonl(remote_endpoint.get_address());
|
||||
|
||||
// UDT doesn't allow now blocking connects...
|
||||
fc::thread connect_thread("connect_thread");
|
||||
connect_thread.async( [&](){
|
||||
if( UDT::ERROR == UDT::connect(_udt_socket_id, (sockaddr*)&serv_addr, sizeof(serv_addr)) )
|
||||
check_udt_errors();
|
||||
}).wait();
|
||||
|
||||
bool block = false;
|
||||
UDT::setsockopt(_udt_socket_id, 0, UDT_SNDSYN, &block, sizeof(bool));
|
||||
UDT::setsockopt(_udt_socket_id, 0, UDT_RCVSYN, &block, sizeof(bool));
|
||||
check_udt_errors();
|
||||
|
||||
} FC_CAPTURE_AND_RETHROW( (remote_endpoint) ) }
|
||||
|
||||
ip::endpoint udt_socket::remote_endpoint() const
|
||||
{ try {
|
||||
sockaddr_in peer_addr;
|
||||
int peer_addr_size = sizeof(peer_addr);
|
||||
int error_code = UDT::getpeername( _udt_socket_id, (struct sockaddr*)&peer_addr, &peer_addr_size );
|
||||
if( error_code == UDT::ERROR )
|
||||
check_udt_errors();
|
||||
return ip::endpoint( ip::address( htonl( peer_addr.sin_addr.s_addr ) ), htons(peer_addr.sin_port) );
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
ip::endpoint udt_socket::local_endpoint() const
|
||||
{ try {
|
||||
sockaddr_in sock_addr;
|
||||
int addr_size = sizeof(sock_addr);
|
||||
int error_code = UDT::getsockname( _udt_socket_id, (struct sockaddr*)&sock_addr, &addr_size );
|
||||
if( error_code == UDT::ERROR )
|
||||
check_udt_errors();
|
||||
return ip::endpoint( ip::address( htonl( sock_addr.sin_addr.s_addr ) ), htons(sock_addr.sin_port) );
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
|
||||
/// @{
|
||||
size_t udt_socket::readsome( char* buffer, size_t max )
|
||||
{ try {
|
||||
auto bytes_read = UDT::recv( _udt_socket_id, buffer, max, 0 );
|
||||
while( bytes_read == UDT::ERROR )
|
||||
{
|
||||
if( UDT::getlasterror().getErrorCode() == CUDTException::EASYNCRCV )
|
||||
{
|
||||
UDT::getlasterror().clear();
|
||||
promise<void>::ptr p(new promise<void>("udt_socket::readsome"));
|
||||
default_epool_service().notify_read( _udt_socket_id, p );
|
||||
p->wait();
|
||||
bytes_read = UDT::recv( _udt_socket_id, buffer, max, 0 );
|
||||
}
|
||||
else
|
||||
check_udt_errors();
|
||||
}
|
||||
return bytes_read;
|
||||
} FC_CAPTURE_AND_RETHROW( (max) ) }
|
||||
|
||||
bool udt_socket::eof()const
|
||||
{
|
||||
// TODO...
|
||||
return false;
|
||||
}
|
||||
/// @}
|
||||
|
||||
/// ostream interface
|
||||
/// @{
|
||||
size_t udt_socket::writesome( const char* buffer, size_t len )
|
||||
{ try {
|
||||
auto bytes_sent = UDT::send(_udt_socket_id, buffer, len, 0);
|
||||
|
||||
while( UDT::ERROR == bytes_sent )
|
||||
{
|
||||
if( UDT::getlasterror().getErrorCode() == CUDTException::EASYNCSND )
|
||||
{
|
||||
UDT::getlasterror().clear();
|
||||
promise<void>::ptr p(new promise<void>("udt_socket::writesome"));
|
||||
default_epool_service().notify_write( _udt_socket_id, p );
|
||||
p->wait();
|
||||
bytes_sent = UDT::send(_udt_socket_id, buffer, len, 0);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
check_udt_errors();
|
||||
}
|
||||
return bytes_sent;
|
||||
} FC_CAPTURE_AND_RETHROW( (len) ) }
|
||||
|
||||
void udt_socket::flush(){}
|
||||
|
||||
void udt_socket::close()
|
||||
{ try {
|
||||
if( is_open() )
|
||||
{
|
||||
default_epool_service().remove( _udt_socket_id );
|
||||
UDT::close( _udt_socket_id );
|
||||
check_udt_errors();
|
||||
_udt_socket_id = UDT::INVALID_SOCK;
|
||||
}
|
||||
else
|
||||
{
|
||||
wlog( "already closed" );
|
||||
}
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
/// @}
|
||||
|
||||
void udt_socket::open()
|
||||
{
|
||||
_udt_socket_id = UDT::socket(AF_INET, SOCK_STREAM, 0);
|
||||
if( _udt_socket_id == UDT::INVALID_SOCK )
|
||||
check_udt_errors();
|
||||
}
|
||||
|
||||
bool udt_socket::is_open()const
|
||||
{
|
||||
return _udt_socket_id != UDT::INVALID_SOCK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
udt_server::udt_server()
|
||||
:_udt_socket_id( UDT::INVALID_SOCK )
|
||||
{
|
||||
_udt_socket_id = UDT::socket(AF_INET, SOCK_STREAM, 0);
|
||||
if( _udt_socket_id == UDT::INVALID_SOCK )
|
||||
check_udt_errors();
|
||||
|
||||
bool block = false;
|
||||
UDT::setsockopt(_udt_socket_id, 0, UDT_SNDSYN, &block, sizeof(bool));
|
||||
check_udt_errors();
|
||||
UDT::setsockopt(_udt_socket_id, 0, UDT_RCVSYN, &block, sizeof(bool));
|
||||
check_udt_errors();
|
||||
}
|
||||
|
||||
udt_server::~udt_server()
|
||||
{
|
||||
try {
|
||||
close();
|
||||
} catch ( const fc::exception& e )
|
||||
{
|
||||
wlog( "${e}", ("e", e.to_detail_string() ) );
|
||||
}
|
||||
}
|
||||
|
||||
void udt_server::close()
|
||||
{ try {
|
||||
if( _udt_socket_id != UDT::INVALID_SOCK )
|
||||
{
|
||||
UDT::close( _udt_socket_id );
|
||||
check_udt_errors();
|
||||
default_epool_service().remove( _udt_socket_id );
|
||||
_udt_socket_id = UDT::INVALID_SOCK;
|
||||
}
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
void udt_server::accept( udt_socket& s )
|
||||
{ try {
|
||||
FC_ASSERT( !s.is_open() );
|
||||
int namelen;
|
||||
sockaddr_in their_addr;
|
||||
|
||||
|
||||
while( s._udt_socket_id == UDT::INVALID_SOCK )
|
||||
{
|
||||
s._udt_socket_id = UDT::accept( _udt_socket_id, (sockaddr*)&their_addr, &namelen );
|
||||
if( UDT::getlasterror().getErrorCode() == CUDTException::EASYNCRCV )
|
||||
{
|
||||
UDT::getlasterror().clear();
|
||||
promise<void>::ptr p(new promise<void>("udt_server::accept"));
|
||||
default_epool_service().notify_read( _udt_socket_id, p );
|
||||
p->wait();
|
||||
s._udt_socket_id = UDT::accept( _udt_socket_id, (sockaddr*)&their_addr, &namelen );
|
||||
}
|
||||
else
|
||||
check_udt_errors();
|
||||
}
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
void udt_server::listen( const ip::endpoint& ep )
|
||||
{ try {
|
||||
sockaddr_in my_addr;
|
||||
my_addr.sin_family = AF_INET;
|
||||
my_addr.sin_port = htons(ep.port());
|
||||
my_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
memset(&(my_addr.sin_zero), '\0', 8);
|
||||
|
||||
if( UDT::ERROR == UDT::bind(_udt_socket_id, (sockaddr*)&my_addr, sizeof(my_addr)) )
|
||||
check_udt_errors();
|
||||
|
||||
UDT::listen(_udt_socket_id, 10);
|
||||
check_udt_errors();
|
||||
} FC_CAPTURE_AND_RETHROW( (ep) ) }
|
||||
|
||||
fc::ip::endpoint udt_server::local_endpoint() const
|
||||
{ try {
|
||||
sockaddr_in sock_addr;
|
||||
int addr_size = sizeof(sock_addr);
|
||||
int error_code = UDT::getsockname( _udt_socket_id, (struct sockaddr*)&sock_addr, &addr_size );
|
||||
if( error_code == UDT::ERROR )
|
||||
check_udt_errors();
|
||||
return ip::endpoint( ip::address( htonl( sock_addr.sin_addr.s_addr ) ), htons(sock_addr.sin_port) );
|
||||
} FC_CAPTURE_AND_RETHROW() }
|
||||
|
||||
}
|
||||
|
|
@ -518,6 +518,42 @@ namespace fc { namespace rpc {
|
|||
my->_out->flush();
|
||||
return my->_awaiting[id];
|
||||
}
|
||||
future<variant> json_connection::async_call( const fc::string& method,
|
||||
const variant& a1,
|
||||
const variant& a2,
|
||||
const variant& a3,
|
||||
const variant& a4, const variant& a5, const variant& a6, const variant& a7, const variant& a8 )
|
||||
{
|
||||
auto id = my->_next_id++;
|
||||
my->_awaiting[id] = fc::promise<variant>::ptr( new fc::promise<variant>() );
|
||||
|
||||
{
|
||||
fc::scoped_lock<fc::mutex> lock(my->_write_mutex);
|
||||
*my->_out << "{\"id\":";
|
||||
*my->_out << id;
|
||||
*my->_out << ",\"method\":";
|
||||
json::to_stream( *my->_out, method );
|
||||
*my->_out << ",\"params\":[";
|
||||
fc::json::to_stream( *my->_out, a1 );
|
||||
*my->_out << ",";
|
||||
fc::json::to_stream( *my->_out, a2 );
|
||||
*my->_out << ",";
|
||||
fc::json::to_stream( *my->_out, a3 );
|
||||
*my->_out << ",";
|
||||
fc::json::to_stream( *my->_out, a4 );
|
||||
*my->_out << ",";
|
||||
fc::json::to_stream( *my->_out, a5 );
|
||||
*my->_out << ",";
|
||||
fc::json::to_stream( *my->_out, a6 );
|
||||
*my->_out << ",";
|
||||
fc::json::to_stream( *my->_out, a7 );
|
||||
*my->_out << ",";
|
||||
fc::json::to_stream( *my->_out, a8 );
|
||||
*my->_out << "]}\n";
|
||||
}
|
||||
my->_out->flush();
|
||||
return my->_awaiting[id];
|
||||
}
|
||||
|
||||
future<variant> json_connection::async_call( const fc::string& method, mutable_variant_object named_args )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -53,15 +53,15 @@ namespace fc {
|
|||
{
|
||||
#if BOOST_VERSION >= 105400
|
||||
bco::stack_context stack_ctx;
|
||||
size_t stack_size = bco::stack_allocator::default_stacksize() * 8;
|
||||
size_t stack_size = bco::stack_allocator::default_stacksize() * 4;
|
||||
alloc.allocate(stack_ctx, stack_size);
|
||||
my_context = bc::make_fcontext( stack_ctx.sp, stack_ctx.size, sf);
|
||||
#elif BOOST_VERSION >= 105300
|
||||
size_t stack_size = bco::stack_allocator::default_stacksize();
|
||||
size_t stack_size = bco::stack_allocator::default_stacksize() * 4;
|
||||
void* stackptr = alloc.allocate(stack_size);
|
||||
my_context = bc::make_fcontext( stackptr, stack_size, sf);
|
||||
#else
|
||||
size_t stack_size = bc::default_stacksize();
|
||||
size_t stack_size = bc::default_stacksize() * 4;
|
||||
my_context.fc_stack.base = alloc.allocate( stack_size );
|
||||
my_context.fc_stack.limit = static_cast<char*>( my_context.fc_stack.base) - stack_size;
|
||||
make_fcontext( &my_context, sf );
|
||||
|
|
@ -91,13 +91,13 @@ namespace fc {
|
|||
delete my_context;
|
||||
#elif BOOST_VERSION >= 105400
|
||||
if(stack_alloc)
|
||||
stack_alloc->deallocate( my_context->fc_stack.sp, bco::stack_allocator::default_stacksize() );
|
||||
stack_alloc->deallocate( my_context->fc_stack.sp, bco::stack_allocator::default_stacksize() * 4 );
|
||||
else
|
||||
delete my_context;
|
||||
|
||||
#elif BOOST_VERSION >= 105300
|
||||
if(stack_alloc)
|
||||
stack_alloc->deallocate( my_context->fc_stack.sp, bco::stack_allocator::default_stacksize() );
|
||||
stack_alloc->deallocate( my_context->fc_stack.sp, bco::stack_allocator::default_stacksize() * 4);
|
||||
else
|
||||
delete my_context;
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -35,7 +35,10 @@ namespace fc {
|
|||
}
|
||||
void task_base::run_impl() {
|
||||
try {
|
||||
_run_functor( _functor, _promise_impl );
|
||||
if( !canceled() )
|
||||
_run_functor( _functor, _promise_impl );
|
||||
else
|
||||
FC_THROW_EXCEPTION( canceled_exception, "${description}", ("description", get_desc() ) );
|
||||
}
|
||||
catch ( const exception& e )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -70,11 +70,11 @@ namespace fc {
|
|||
return t;
|
||||
}
|
||||
|
||||
thread::thread( const char* name ) {
|
||||
thread::thread( const std::string& name ) {
|
||||
promise<void>::ptr p(new promise<void>());
|
||||
boost::thread* t = new boost::thread( [this,p,name]() {
|
||||
try {
|
||||
set_thread_name(name); // set thread's name for the debugger to display
|
||||
set_thread_name(name.c_str()); // set thread's name for the debugger to display
|
||||
this->my = new thread_d(*this);
|
||||
current_thread() = this;
|
||||
p->set_value();
|
||||
|
|
@ -108,7 +108,7 @@ namespace fc {
|
|||
}
|
||||
|
||||
thread::~thread() {
|
||||
//slog( "my %p", my );
|
||||
//wlog( "my ${n}", ("n",name()) );
|
||||
if( is_current() )
|
||||
{
|
||||
wlog( "delete my" );
|
||||
|
|
@ -126,22 +126,20 @@ namespace fc {
|
|||
void thread::debug( const fc::string& d ) { /*my->debug(d);*/ }
|
||||
|
||||
void thread::quit() {
|
||||
//if quiting from a different thread, start quit task on thread.
|
||||
//if quitting from a different thread, start quit task on thread.
|
||||
//If we have and know our attached boost thread, wait for it to finish, then return.
|
||||
if( ¤t() != this ) {
|
||||
async( [=](){quit();} );//.wait();
|
||||
if( my->boost_thread ) {
|
||||
auto n = name();
|
||||
ilog( "joining... ${n}", ("n",n) );//n.c_str() );
|
||||
my->boost_thread->join();
|
||||
delete my;
|
||||
my = nullptr;
|
||||
ilog( "done joining...${n}", ("n",n) ); //n.c_str() );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// wlog( "%s", my->name.c_str() );
|
||||
wlog( "${s}", ("s",name()) );
|
||||
// We are quiting from our own thread...
|
||||
|
||||
// break all promises, thread quit!
|
||||
|
|
@ -157,8 +155,8 @@ namespace fc {
|
|||
cur = n;
|
||||
}
|
||||
if( my->blocked ) {
|
||||
// wlog( "still blocking... whats up with that?");
|
||||
// debug( "on quit" );
|
||||
wlog( "still blocking... whats up with that?");
|
||||
debug( "on quit" );
|
||||
}
|
||||
}
|
||||
BOOST_ASSERT( my->blocked == 0 );
|
||||
|
|
@ -200,7 +198,7 @@ namespace fc {
|
|||
void thread::exec() {
|
||||
if( !my->current ) my->current = new fc::context(&fc::thread::current());
|
||||
try {
|
||||
my->process_tasks();
|
||||
my->process_tasks();
|
||||
}
|
||||
catch( canceled_exception& )
|
||||
{
|
||||
|
|
@ -225,35 +223,15 @@ namespace fc {
|
|||
my->start_next_fiber(reschedule);
|
||||
my->check_fiber_exceptions();
|
||||
}
|
||||
|
||||
void thread::sleep_until( const time_point& tp ) {
|
||||
//ilog( "sleep until ${tp} wait: ${delta}", ("tp",tp)("delta",(tp-fc::time_point::now()).count()) );
|
||||
|
||||
if( tp <= (time_point::now()+fc::microseconds(10000)) )
|
||||
{
|
||||
this->yield(true);
|
||||
}
|
||||
my->yield_until( tp, false );
|
||||
/*
|
||||
my->check_fiber_exceptions();
|
||||
|
||||
BOOST_ASSERT( ¤t() == this );
|
||||
if( !my->current ) {
|
||||
my->current = new fc::context(&fc::thread::current());
|
||||
}
|
||||
|
||||
my->current->resume_time = tp;
|
||||
my->current->clear_blocking_promises();
|
||||
|
||||
my->sleep_pqueue.push_back(my->current);
|
||||
std::push_heap( my->sleep_pqueue.begin(),
|
||||
my->sleep_pqueue.end(), sleep_priority_less() );
|
||||
|
||||
my->start_next_fiber();
|
||||
my->current->resume_time = time_point::maximum();
|
||||
|
||||
my->check_fiber_exceptions();
|
||||
*/
|
||||
}
|
||||
|
||||
int thread::wait_any_until( std::vector<promise_base::ptr>&& p, const time_point& timeout) {
|
||||
for( size_t i = 0; i < p.size(); ++i ) {
|
||||
if( p[i]->ready() ) return i;
|
||||
|
|
|
|||
|
|
@ -239,6 +239,30 @@ namespace fc {
|
|||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
bool process_canceled_tasks()
|
||||
{
|
||||
bool canceled_task = false;
|
||||
for( auto task_itr = task_sch_queue.begin();
|
||||
task_itr != task_sch_queue.end();
|
||||
)
|
||||
{
|
||||
if( (*task_itr)->canceled() )
|
||||
{
|
||||
(*task_itr)->run();
|
||||
(*task_itr)->release();
|
||||
task_itr = task_sch_queue.erase(task_itr);
|
||||
canceled_task = true;
|
||||
continue;
|
||||
}
|
||||
++task_itr;
|
||||
}
|
||||
|
||||
if( canceled_task )
|
||||
std::make_heap( task_sch_queue.begin(), task_sch_queue.end(), task_when_less() );
|
||||
|
||||
return canceled_task;
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be before or after a context switch to
|
||||
|
|
@ -341,6 +365,7 @@ namespace fc {
|
|||
bool run_next_task() {
|
||||
check_for_timeouts();
|
||||
task_base* next = dequeue();
|
||||
|
||||
if( next ) {
|
||||
next->_set_active_context( current );
|
||||
current->cur_task = next;
|
||||
|
|
@ -377,6 +402,8 @@ namespace fc {
|
|||
continue;
|
||||
}
|
||||
|
||||
if( process_canceled_tasks() ) continue;
|
||||
|
||||
clear_free_list();
|
||||
|
||||
{ // lock scope
|
||||
|
|
@ -388,6 +415,10 @@ namespace fc {
|
|||
if( timeout_time == time_point::maximum() ) {
|
||||
task_ready.wait( lock );
|
||||
} else if( timeout_time != time_point::min() ) {
|
||||
// there may be tasks that have been canceled we should filter them out now
|
||||
// rather than waiting...
|
||||
|
||||
|
||||
/* This bit is kind of sloppy -- this wait was originally implemented as a wait
|
||||
* with respect to boost::chrono::system_clock. This behaved rather comically
|
||||
* if you were to do a:
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ namespace fc {
|
|||
return result.str();
|
||||
}
|
||||
uint32_t years_ago = days_ago / 365;
|
||||
result << years_ago << " year" << (months_ago > 1 ? "s" : "");
|
||||
result << years_ago << " year" << (months_ago > 1 ? "s " : " ");
|
||||
if (months_ago < 12 * 5)
|
||||
{
|
||||
uint32_t leftover_days = days_ago - (years_ago * 365);
|
||||
|
|
|
|||
24
tests/lzma_test.cpp
Normal file
24
tests/lzma_test.cpp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#include <fc/compress/lzma.hpp>
|
||||
#include <fc/filesystem.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
using namespace fc;
|
||||
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
if( argc != 2 )
|
||||
{
|
||||
std::cout << "usage: " << argv[0] << " <filename>\n";
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
auto src = std::string( argv[1] );
|
||||
auto dst = src + ".compressed";
|
||||
lzma_compress_file( src, dst );
|
||||
|
||||
lzma_decompress_file( dst, src + ".decompressed" );
|
||||
|
||||
return 0;
|
||||
}
|
||||
92
tests/task_cancel.cpp
Normal file
92
tests/task_cancel.cpp
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
#define BOOST_TEST_MODULE fc_task_cancel_tests
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <fc/thread/thread.hpp>
|
||||
#include <fc/log/logger.hpp>
|
||||
#include <fc/exception/exception.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_CASE( cancel_an_active_task )
|
||||
{
|
||||
enum task_result{sleep_completed, sleep_aborted};
|
||||
fc::future<task_result> task = fc::async([]() {
|
||||
BOOST_TEST_MESSAGE("Starting async task");
|
||||
try
|
||||
{
|
||||
fc::usleep(fc::seconds(5));
|
||||
return sleep_completed;
|
||||
}
|
||||
catch (const fc::exception&)
|
||||
{
|
||||
return sleep_aborted;
|
||||
}
|
||||
});
|
||||
|
||||
fc::time_point start_time = fc::time_point::now();
|
||||
|
||||
// wait a bit for the task to start running
|
||||
fc::usleep(fc::milliseconds(100));
|
||||
|
||||
BOOST_TEST_MESSAGE("Canceling task");
|
||||
task.cancel();
|
||||
try
|
||||
{
|
||||
task_result result = task.wait();
|
||||
BOOST_CHECK_MESSAGE(result != sleep_completed, "sleep should have been canceled");
|
||||
}
|
||||
catch (fc::exception& e)
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Caught exception from canceled task: " << e.what());
|
||||
BOOST_CHECK_MESSAGE(fc::time_point::now() - start_time < fc::seconds(4), "Task was not canceled quickly");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( cleanup_cancelled_task )
|
||||
{
|
||||
std::shared_ptr<std::string> some_string(std::make_shared<std::string>("some string"));
|
||||
fc::future<void> task = fc::async([some_string]() {
|
||||
BOOST_TEST_MESSAGE("Starting async task, bound string is " << *some_string);
|
||||
try
|
||||
{
|
||||
fc::usleep(fc::seconds(5));
|
||||
BOOST_TEST_MESSAGE("Finsihed usleep in async task, leaving the task's functor");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Caught exception in async task, leaving the task's functor");
|
||||
}
|
||||
});
|
||||
std::weak_ptr<std::string> weak_string_ptr(some_string);
|
||||
some_string.reset();
|
||||
BOOST_CHECK_MESSAGE(!weak_string_ptr.expired(), "Weak pointer should still be valid because async task should be holding the strong pointer");
|
||||
fc::usleep(fc::milliseconds(100));
|
||||
BOOST_TEST_MESSAGE("Canceling task");
|
||||
task.cancel();
|
||||
try
|
||||
{
|
||||
task.wait();
|
||||
}
|
||||
catch (fc::exception& e)
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Caught exception from canceled task: " << e.what());
|
||||
}
|
||||
BOOST_CHECK_MESSAGE(weak_string_ptr.expired(), "Weak pointer should now be invalid because async task should be done with it");
|
||||
task = fc::future<void>();
|
||||
BOOST_CHECK_MESSAGE(weak_string_ptr.expired(), "Weak pointer should now be invalid because async task should have been destroyed");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( cancel_scheduled_task )
|
||||
{
|
||||
bool task_executed = false;
|
||||
try
|
||||
{
|
||||
auto result = fc::schedule( [&]() { task_executed = true; }, fc::time_point::now() + fc::seconds(3) );
|
||||
result.cancel();
|
||||
result.wait();
|
||||
}
|
||||
catch ( const fc::exception& e )
|
||||
{
|
||||
wlog( "${e}", ("e",e.to_detail_string() ) );
|
||||
}
|
||||
BOOST_CHECK(!task_executed);
|
||||
}
|
||||
36
tests/udt_client.cpp
Normal file
36
tests/udt_client.cpp
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#include <iostream>
|
||||
#include <udt.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace UDT;
|
||||
|
||||
int main()
|
||||
{
|
||||
UDTSOCKET client = UDT::socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
sockaddr_in serv_addr;
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_port = htons(9000);
|
||||
inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);
|
||||
|
||||
memset(&(serv_addr.sin_zero), '\0', 8);
|
||||
|
||||
// connect to the server, implict bind
|
||||
if (UDT::ERROR == UDT::connect(client, (sockaddr*)&serv_addr, sizeof(serv_addr)))
|
||||
{
|
||||
cout << "connect: " << UDT::getlasterror().getErrorMessage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* hello = "hello world! 3\n";
|
||||
if (UDT::ERROR == UDT::send(client, hello, strlen(hello) + 1, 0))
|
||||
{
|
||||
cout << "send: " << UDT::getlasterror().getErrorMessage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
UDT::close(client);
|
||||
|
||||
return 1;
|
||||
}
|
||||
83
tests/udt_server.cpp
Normal file
83
tests/udt_server.cpp
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <udt.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
UDTSOCKET serv = UDT::socket(AF_INET, SOCK_STREAM, 0);
|
||||
bool block = false;
|
||||
|
||||
sockaddr_in my_addr;
|
||||
my_addr.sin_family = AF_INET;
|
||||
my_addr.sin_port = htons(9000);
|
||||
my_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
memset(&(my_addr.sin_zero), '\0', 8);
|
||||
|
||||
if (UDT::ERROR == UDT::bind(serv, (sockaddr*)&my_addr, sizeof(my_addr)))
|
||||
{
|
||||
cout << "bind: " << UDT::getlasterror().getErrorMessage();
|
||||
return 0;
|
||||
}
|
||||
UDT::listen(serv, 10);
|
||||
|
||||
int namelen;
|
||||
sockaddr_in their_addr;
|
||||
|
||||
|
||||
UDT::setsockopt(serv, 0, UDT_SNDSYN, &block, sizeof(bool));
|
||||
UDT::setsockopt(serv, 0, UDT_RCVSYN, &block, sizeof(bool));
|
||||
UDTSOCKET recver = UDT::accept(serv, (sockaddr*)&their_addr, &namelen);
|
||||
if( recver == UDT::INVALID_SOCK )
|
||||
{
|
||||
if( UDT::getlasterror_code() == CUDTException::EASYNCRCV )
|
||||
{
|
||||
std::cout << "nothing yet... better luck next time\n";
|
||||
}
|
||||
}
|
||||
auto pollid = UDT::epoll_create();
|
||||
UDT::epoll_add_usock(pollid, serv, nullptr );// const int* events = NULL);
|
||||
std::set<UDTSOCKET> readready;
|
||||
std::set<UDTSOCKET> writeready;
|
||||
std::cout << "waiting for 5 seconds\n";
|
||||
UDT::epoll_wait( pollid, &readready, &writeready, 10000 );
|
||||
|
||||
|
||||
recver = UDT::accept(serv, (sockaddr*)&their_addr, &namelen);
|
||||
if( recver == UDT::INVALID_SOCK )
|
||||
{
|
||||
if( UDT::getlasterror_code() == CUDTException::EASYNCRCV )
|
||||
{
|
||||
std::cout << "nothing yet... better luck next time\n";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
UDT::setsockopt(recver, 0, UDT_SNDSYN, &block, sizeof(bool));
|
||||
UDT::setsockopt(recver, 0, UDT_RCVSYN, &block, sizeof(bool));
|
||||
UDT::epoll_remove_usock(pollid, serv );// const int* events = NULL);
|
||||
int events = UDT_EPOLL_IN;
|
||||
|
||||
UDT::epoll_add_usock(pollid, recver, &events );// const int* events = NULL);
|
||||
|
||||
readready.clear();
|
||||
UDT::epoll_wait( pollid, &readready, &writeready, 5000 );
|
||||
|
||||
char ip[16];
|
||||
cout << "new connection: " << inet_ntoa(their_addr.sin_addr) << ":" << ntohs(their_addr.sin_port) << endl;
|
||||
|
||||
char data[100];
|
||||
|
||||
while (UDT::ERROR == UDT::recv(recver, data, 100, 0))
|
||||
{
|
||||
cout << "recv:" << UDT::getlasterror().getErrorMessage() << endl;
|
||||
UDT::epoll_wait( pollid, &readready, &writeready, 5000 );
|
||||
}
|
||||
|
||||
cout << data << endl;
|
||||
|
||||
UDT::close(recver);
|
||||
UDT::close(serv);
|
||||
|
||||
return 1;
|
||||
}
|
||||
49
tests/udtc.cpp
Normal file
49
tests/udtc.cpp
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#include <fc/network/udt_socket.hpp>
|
||||
#include <fc/network/ip.hpp>
|
||||
#include <fc/exception/exception.hpp>
|
||||
#include <fc/thread/thread.hpp>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
using namespace fc;
|
||||
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
try {
|
||||
udt_socket sock;
|
||||
sock.bind( fc::ip::endpoint::from_string( "127.0.0.1:6666" ) );
|
||||
ilog( "." );
|
||||
sock.connect_to( fc::ip::endpoint::from_string( "127.0.0.1:7777" ) );
|
||||
ilog( "after connect to..." );
|
||||
|
||||
std::cout << "local endpoint: " <<std::string( sock.local_endpoint() ) <<"\n";
|
||||
std::cout << "remote endpoint: " <<std::string( sock.remote_endpoint() ) <<"\n";
|
||||
|
||||
std::string hello = "hello world\n";
|
||||
for( uint32_t i = 0; i < 1000000; ++i )
|
||||
{
|
||||
sock.write( hello.c_str(), hello.size() );
|
||||
}
|
||||
ilog( "closing" );
|
||||
sock.close();
|
||||
usleep( fc::seconds(1) );
|
||||
/*
|
||||
std::vector<char> response;
|
||||
response.resize(1024);
|
||||
int r = sock.readsome( response.data(), response.size() );
|
||||
while( r )
|
||||
{
|
||||
std::cout.write( response.data(), r );
|
||||
r = sock.readsome( response.data(), response.size() );
|
||||
}
|
||||
*/
|
||||
// if we exit too quickly, UDT will not have a chance to
|
||||
// send the graceful close message.
|
||||
//fc::usleep( fc::seconds(1) );
|
||||
} catch ( const fc::exception& e )
|
||||
{
|
||||
elog( "${e}", ("e",e.to_detail_string() ) );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
39
tests/udts.cpp
Normal file
39
tests/udts.cpp
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#include <fc/network/udt_socket.hpp>
|
||||
#include <fc/network/ip.hpp>
|
||||
#include <fc/exception/exception.hpp>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
using namespace fc;
|
||||
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
try {
|
||||
udt_server serv;
|
||||
serv.listen( fc::ip::endpoint::from_string( "127.0.0.1:7777" ) );
|
||||
|
||||
while( true )
|
||||
{
|
||||
udt_socket sock;
|
||||
serv.accept( sock );
|
||||
|
||||
std::vector<char> response;
|
||||
response.resize(1024);
|
||||
int r = sock.readsome( response.data(), response.size() );
|
||||
while( r )
|
||||
{
|
||||
std::cout.write( response.data(), r );
|
||||
r = sock.readsome( response.data(), response.size() );
|
||||
//sock.write( response.data(), response.size() );
|
||||
}
|
||||
|
||||
std::string goodbye = "goodbye cruel world";
|
||||
sock.write( goodbye.c_str(), goodbye.size() );
|
||||
}
|
||||
} catch ( const fc::exception& e )
|
||||
{
|
||||
elog( "${e}", ("e",e.to_detail_string() ) );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
8
vendor/easylzma/src/CMakeLists.txt
vendored
8
vendor/easylzma/src/CMakeLists.txt
vendored
|
|
@ -52,8 +52,8 @@ ENDIF (APPLE)
|
|||
|
||||
### copy the two required headers into our output dir as a post build step
|
||||
# copy public headers to output directory
|
||||
FOREACH (header ${PUB_HDRS})
|
||||
#FOREACH (header ${PUB_HDRS})
|
||||
# preserve relative pathing
|
||||
ADD_CUSTOM_COMMAND(TARGET easylzma_s POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${header} ${incDir})
|
||||
ENDFOREACH (header ${PUB_HDRS})
|
||||
#ADD_CUSTOM_COMMAND(TARGET easylzma_s POST_BUILD
|
||||
#COMMAND ${CMAKE_COMMAND} -E copy_if_different ${header} ${incDir})
|
||||
#ENDFOREACH (header ${PUB_HDRS})
|
||||
|
|
|
|||
12
vendor/scrypt-jane/CMakeLists.txt
vendored
Normal file
12
vendor/scrypt-jane/CMakeLists.txt
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
if( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -no-integrated-as" )
|
||||
endif()
|
||||
|
||||
add_definitions( -DSCRYPT_SALSA )
|
||||
add_definitions( -DSCRYPT_SHA256 )
|
||||
|
||||
set( scrypt_sources
|
||||
scrypt-jane.c
|
||||
)
|
||||
|
||||
add_library( scrypt ${scrypt_sources} )
|
||||
12
vendor/scrypt-jane/scrypt-jane.h
vendored
12
vendor/scrypt-jane/scrypt-jane.h
vendored
|
|
@ -19,9 +19,15 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef void (*scrypt_fatal_errorfn)(const char *msg);
|
||||
void scrypt_set_fatal_error(scrypt_fatal_errorfn fn);
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
typedef void (*scrypt_fatal_errorfn)(const char *msg);
|
||||
void scrypt_set_fatal_error(scrypt_fatal_errorfn fn);
|
||||
|
||||
void scrypt(const unsigned char *password, size_t password_len, const unsigned char *salt, size_t salt_len, unsigned char Nfactor, unsigned char rfactor, unsigned char pfactor, unsigned char *out, size_t bytes);
|
||||
void scrypt(const unsigned char *password, size_t password_len, const unsigned char *salt, size_t salt_len, unsigned char Nfactor, unsigned char rfactor, unsigned char pfactor, unsigned char *out, size_t bytes);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SCRYPT_JANE_H */
|
||||
|
|
|
|||
Loading…
Reference in a new issue