moving more functions from mace to fc
This commit is contained in:
parent
460da34801
commit
018609fafa
21 changed files with 746 additions and 32 deletions
|
|
@ -66,6 +66,9 @@ set( sources
|
|||
src/ip.cpp
|
||||
src/bigint.cpp
|
||||
src/mutex.cpp
|
||||
src/pke.cpp
|
||||
src/base64.cpp
|
||||
src/udp_socket.cpp
|
||||
)
|
||||
setup_library( fc SOURCES ${sources} )
|
||||
|
||||
|
|
|
|||
|
|
@ -5,17 +5,18 @@
|
|||
#ifndef _FC_ASIO_HPP_
|
||||
#define _FC_ASIO_HPP_
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <fc/future.hpp>
|
||||
#include <boost/iostreams/stream.hpp>
|
||||
#include <boost/iostreams/combine.hpp>
|
||||
|
||||
namespace fc {
|
||||
/**
|
||||
* @brief defines fc::cmt wrappers for boost::asio functions.
|
||||
* @brief defines fc wrappers for boost::asio functions.
|
||||
*/
|
||||
namespace asio {
|
||||
/**
|
||||
* @brief internal implementation types/methods for fc::cmt::asio
|
||||
* @brief internal implementation types/methods for fc::asio
|
||||
*/
|
||||
namespace detail {
|
||||
using namespace fc;
|
||||
|
|
@ -48,7 +49,7 @@ namespace asio {
|
|||
#endif
|
||||
}
|
||||
/**
|
||||
* @return the default boost::asio::io_service for use with fc::cmt::asio
|
||||
* @return the default boost::asio::io_service for use with fc::asio
|
||||
*
|
||||
* This IO service is automatically running in its own thread to service asynchronous
|
||||
* requests without blocking any other threads.
|
||||
|
|
@ -74,7 +75,7 @@ namespace asio {
|
|||
BOOST_THROW_EXCEPTION( boost::system::system_error(ec) );
|
||||
}
|
||||
|
||||
promise<size_t>::ptr p(new promise<size_t>("fc::cmt::asio::read"));
|
||||
promise<size_t>::ptr p(new promise<size_t>("fc::asio::read"));
|
||||
boost::asio::async_read( s, buf, boost::bind( detail::read_write_handler, p, _1, _2 ) );
|
||||
return p->wait();
|
||||
}
|
||||
|
|
@ -105,7 +106,7 @@ namespace asio {
|
|||
BOOST_THROW_EXCEPTION( boost::system::system_error(ec) );
|
||||
}
|
||||
|
||||
promise<size_t>::ptr p(new promise<size_t>("fc::cmt::asio::read_some"));
|
||||
promise<size_t>::ptr p(new promise<size_t>("fc::asio::read_some"));
|
||||
s.async_read_some( buf, boost::bind( detail::read_write_handler, p, _1, _2 ) );
|
||||
return p->wait();
|
||||
}
|
||||
|
|
@ -125,7 +126,7 @@ namespace asio {
|
|||
BOOST_THROW_EXCEPTION( boost::system::system_error(ec) );
|
||||
}
|
||||
}
|
||||
promise<size_t>::ptr p(new promise<size_t>("fc::cmt::asio::write"));
|
||||
promise<size_t>::ptr p(new promise<size_t>("fc::asio::write"));
|
||||
boost::asio::async_write(s, buf, boost::bind( detail::read_write_handler, p, _1, _2 ) );
|
||||
return p->wait();
|
||||
}
|
||||
|
|
@ -147,7 +148,7 @@ namespace asio {
|
|||
BOOST_THROW_EXCEPTION( boost::system::system_error(ec) );
|
||||
}
|
||||
}
|
||||
promise<size_t>::ptr p(new promise<size_t>("fc::cmt::asio::write_some"));
|
||||
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();
|
||||
}
|
||||
|
|
@ -161,7 +162,7 @@ namespace asio {
|
|||
sink( AsyncWriteStream& p ):m_stream(p){}
|
||||
|
||||
std::streamsize write( const char* s, std::streamsize n ) {
|
||||
return fc::cmt::asio::write( m_stream, boost::asio::const_buffers_1(s,n) );
|
||||
return fc::asio::write( m_stream, boost::asio::const_buffers_1(s,n) );
|
||||
}
|
||||
void close() { m_stream.close(); }
|
||||
|
||||
|
|
@ -178,7 +179,7 @@ namespace asio {
|
|||
source( AsyncReadStream& p ):m_stream(p){}
|
||||
|
||||
std::streamsize read( char* s, std::streamsize n ) {
|
||||
return fc::cmt::asio::read_some( m_stream, boost::asio::buffer(s,n) );
|
||||
return fc::asio::read_some( m_stream, boost::asio::buffer(s,n) );
|
||||
}
|
||||
void close() { m_stream.close(); }
|
||||
|
||||
|
|
@ -194,11 +195,11 @@ namespace asio {
|
|||
io_device( AsyncStream& p ):m_stream(p){}
|
||||
|
||||
std::streamsize write( const char* s, std::streamsize n ) {
|
||||
return fc::cmt::asio::write( m_stream, boost::asio::const_buffers_1(s,static_cast<size_t>(n)) );
|
||||
return fc::asio::write( m_stream, boost::asio::const_buffers_1(s,static_cast<size_t>(n)) );
|
||||
}
|
||||
std::streamsize read( char* s, std::streamsize n ) {
|
||||
try {
|
||||
return fc::cmt::asio::read_some( m_stream, boost::asio::buffer(s,n) );
|
||||
return fc::asio::read_some( m_stream, boost::asio::buffer(s,n) );
|
||||
} catch ( const boost::system::system_error& e ) {
|
||||
if( e.code() == boost::asio::error::eof )
|
||||
return -1;
|
||||
|
|
@ -225,8 +226,8 @@ namespace asio {
|
|||
*/
|
||||
template<typename SocketType, typename AcceptorType>
|
||||
void accept( AcceptorType& acc, SocketType& sock ) {
|
||||
promise<boost::system::error_code>::ptr p( new promise<boost::system::error_code>("fc::cmt::asio::tcp::accept") );
|
||||
acc.async_accept( sock, boost::bind( fc::cmt::asio::detail::error_handler, p, _1 ) );
|
||||
promise<boost::system::error_code>::ptr p( new promise<boost::system::error_code>("fc::asio::tcp::accept") );
|
||||
acc.async_accept( sock, boost::bind( fc::asio::detail::error_handler, p, _1 ) );
|
||||
auto ec = p->wait();
|
||||
if( !ec ) sock.non_blocking(true);
|
||||
if( ec ) BOOST_THROW_EXCEPTION( boost::system::system_error(ec) );
|
||||
|
|
@ -238,16 +239,16 @@ namespace asio {
|
|||
*/
|
||||
template<typename AsyncSocket, typename EndpointType>
|
||||
void connect( AsyncSocket& sock, const EndpointType& ep ) {
|
||||
promise<boost::system::error_code>::ptr p(new promise<boost::system::error_code>("fc::cmt::asio::tcp::connect"));
|
||||
sock.async_connect( ep, boost::bind( fc::cmt::asio::detail::error_handler, p, _1 ) );
|
||||
promise<boost::system::error_code>::ptr p(new promise<boost::system::error_code>("fc::asio::tcp::connect"));
|
||||
sock.async_connect( ep, boost::bind( fc::asio::detail::error_handler, p, _1 ) );
|
||||
auto ec = p->wait();
|
||||
if( !ec ) sock.non_blocking(true);
|
||||
if( ec ) BOOST_THROW_EXCEPTION( boost::system::system_error(ec) );
|
||||
}
|
||||
|
||||
typedef boost::iostreams::stream<fc::cmt::asio::sink<boost::asio::ip::tcp::socket> > ostream;
|
||||
typedef boost::iostreams::stream<fc::cmt::asio::source<boost::asio::ip::tcp::socket> > istream;
|
||||
typedef boost::iostreams::stream<fc::cmt::asio::io_device<boost::asio::ip::tcp::socket> > iostream;
|
||||
typedef boost::iostreams::stream<fc::asio::sink<boost::asio::ip::tcp::socket> > ostream;
|
||||
typedef boost::iostreams::stream<fc::asio::source<boost::asio::ip::tcp::socket> > istream;
|
||||
typedef boost::iostreams::stream<fc::asio::io_device<boost::asio::ip::tcp::socket> > iostream;
|
||||
|
||||
}
|
||||
namespace udp {
|
||||
|
|
|
|||
10
include/fc/base64.hpp
Normal file
10
include/fc/base64.hpp
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef _FC_BASE64_HPP
|
||||
#define _FC_BASE64_HPP
|
||||
#include <fc/string.hpp>
|
||||
|
||||
namespace fc {
|
||||
fc::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len);
|
||||
fc::string base64_encode( const fc::string& enc );
|
||||
fc::string base64_decode( const fc::string& encoded_string);
|
||||
} // namespace fc
|
||||
#endif // _FC_BASE64_HPP
|
||||
112
include/fc/datastream.hpp
Normal file
112
include/fc/datastream.hpp
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
#ifndef _FC_DATASTREAM_HPP_
|
||||
#define _FC_DATASTREAM_HPP_
|
||||
#include <fc/utility.hpp>
|
||||
#include <fc/exception.hpp>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace fc {
|
||||
|
||||
/**
|
||||
* The purpose of this datastream is to provide a fast, effecient, means
|
||||
* of calculating the amount of data "about to be written" and then
|
||||
* writing it. This means having two modes of operation, "test run" where
|
||||
* you call the entire pack sequence calculating the size, and then
|
||||
* actually packing it after doing a single allocation.
|
||||
*/
|
||||
template<typename T>
|
||||
struct datastream {
|
||||
datastream( T start, uint32_t s )
|
||||
:m_start(start),m_pos(start),m_end(start+s){};
|
||||
|
||||
template<typename DATA>
|
||||
inline datastream& operator<<(const DATA& d) {
|
||||
static_assert( !fc::is_class<DATA>::value, "no serialization defined" );
|
||||
write( (const char*)&d, sizeof(d) );
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename DATA>
|
||||
inline datastream& operator>>(DATA& d) {
|
||||
static_assert( !fc::is_class<DATA>::value, "no serialization defined" );
|
||||
read((char*)&d, sizeof(d) );
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void skip( uint32_t s ){ m_pos += s; }
|
||||
inline bool read( char* d, uint32_t s ) {
|
||||
if( m_end - m_pos >= (int32_t)s ) {
|
||||
memcpy( d, m_pos, s );
|
||||
m_pos += s;
|
||||
return true;
|
||||
}
|
||||
FC_THROW( "Attempt to read %d bytes beyond end of buffer of size %d", -((m_end-m_pos) - s),(m_end-m_start) );
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool write( const char* d, uint32_t s ) {
|
||||
if( m_end - m_pos >= (int32_t)s ) {
|
||||
memcpy( m_pos, d, s );
|
||||
m_pos += s;
|
||||
return true;
|
||||
}
|
||||
FC_THROW( "Attempt to write %d bytes beyond end of buffer of size %d",%-((m_end-m_pos) - s),(m_end-m_start) );
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool put(char c) {
|
||||
if( m_pos < m_end ) {
|
||||
*m_pos = c;
|
||||
++m_pos;
|
||||
return true;
|
||||
}
|
||||
FC_THROW( "Attempt to write %d byte beyond end of buffer of size %d", -((m_end-m_pos) - 1), (m_end-m_start) );
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool get( unsigned char& c ) { return get( *(char*)&c ); }
|
||||
inline bool get( char& c ) {
|
||||
if( m_pos < m_end ) {
|
||||
c = *m_pos;
|
||||
++m_pos;
|
||||
return true;
|
||||
}
|
||||
FC_THROW( "Attempt to read %d byte beyond end of buffer of size %d", -((m_end-m_pos) - 1), (m_end-m_start) );
|
||||
++m_pos;
|
||||
return false;
|
||||
}
|
||||
|
||||
T pos()const { return m_pos; }
|
||||
inline bool valid()const { return m_pos <= m_end && m_pos >= m_start; }
|
||||
inline bool seekp(uint32_t p) { m_pos = m_start + p; return m_pos <= m_end; }
|
||||
inline uint32_t tellp()const { return m_pos - m_start; }
|
||||
inline uint32_t remaining()const { return m_end - m_pos; }
|
||||
private:
|
||||
T m_start;
|
||||
T m_pos;
|
||||
T m_end;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct datastream<size_t> {
|
||||
datastream( size_t init_size = 0):m_size(init_size){};
|
||||
template<typename DATA>
|
||||
inline datastream& operator<<(const DATA& d) {
|
||||
static_assert( !fc::is_class<DATA>::value, "no serialzation defined" );
|
||||
m_size += sizeof(d);
|
||||
return *this;
|
||||
}
|
||||
inline bool skip( uint32_t s ) { m_size += s; return true; }
|
||||
inline bool write( const char* d, uint32_t s ) { m_size += s; return true; }
|
||||
inline bool put(char c) { ++m_size; return true; }
|
||||
inline bool valid()const { return true; }
|
||||
inline bool seekp(uint32_t p) { m_size = p; return true; }
|
||||
inline uint32_t tellp()const { return m_size; }
|
||||
inline uint32_t remaining()const { return 0; }
|
||||
private:
|
||||
uint32_t m_size;
|
||||
};
|
||||
|
||||
|
||||
} // namespace fc
|
||||
|
||||
#endif
|
||||
|
|
@ -1,11 +1,26 @@
|
|||
#ifndef _FC_ERROR_HPP_
|
||||
#define _FC_ERROR_HPP_
|
||||
#include <fc/string.hpp>
|
||||
|
||||
namespace fc {
|
||||
struct future_wait_timeout: public std::exception{};
|
||||
struct task_canceled: public std::exception{};
|
||||
struct thread_quit: public std::exception{};
|
||||
struct wait_any_error: public std::exception{};
|
||||
|
||||
struct pke_exception : public std::exception {};
|
||||
struct invalid_buffer_length : public pke_exception {};
|
||||
struct invalid_key_length : public pke_exception {};
|
||||
|
||||
struct generic_exception : public std::exception {
|
||||
generic_exception( const fc::string& msg = "" ):m_msg(msg){}
|
||||
~generic_exception()throw() {}
|
||||
const char* what()const throw() { return m_msg.c_str(); }
|
||||
private:
|
||||
fc::string m_msg;
|
||||
};
|
||||
|
||||
|
||||
struct bad_cast: public std::exception{
|
||||
const char* what()const throw(){ return "bad cast"; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ namespace fc {
|
|||
~path();
|
||||
path( const boost::filesystem::path& );
|
||||
path( const fc::string& p );
|
||||
path( const char* );
|
||||
path( const path& p );
|
||||
path( path&& p );
|
||||
path& operator =( const path& );
|
||||
|
|
|
|||
|
|
@ -55,23 +55,28 @@ namespace fc {
|
|||
bool fwd<T,S,A>::operator !()const { return !(**this); }
|
||||
|
||||
|
||||
template<uint64_t RequiredSize, uint64_t ProvidedSize>
|
||||
void check_size() { static_assert( (ProvidedSize >= RequiredSize), "Failed to reserve enough space in fc::fwd<T,S>" ); }
|
||||
|
||||
template<typename T,unsigned int S,typename A>
|
||||
template<typename U>
|
||||
fwd<T,S,A>::fwd( U&& u ) {
|
||||
static_assert( sizeof(_store) >= sizeof(*this), "Failed to reserve enough space" );
|
||||
check_size<sizeof(T),sizeof(_store)>();
|
||||
new (this) T( fc::forward<U>(u) );
|
||||
}
|
||||
template<typename T,unsigned int S,typename A>
|
||||
fwd<T,S,A>::fwd() {
|
||||
static_assert( sizeof(_store) >= sizeof(*this), "Failed to reserve enough space" );
|
||||
check_size<sizeof(T),sizeof(_store)>();
|
||||
new (this) T();
|
||||
}
|
||||
template<typename T,unsigned int S,typename A>
|
||||
fwd<T,S,A>::fwd( const fwd<T,S,A>& f ){
|
||||
check_size<sizeof(T),sizeof(_store)>();
|
||||
new (this) T( *f );
|
||||
}
|
||||
template<typename T,unsigned int S,typename A>
|
||||
fwd<T,S,A>::fwd( fwd<T,S,A>&& f ){
|
||||
check_size<sizeof(T),sizeof(_store)>();
|
||||
new (this) T( fc::move(*f) );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@ namespace fc {
|
|||
|
||||
address& operator=( const fc::string& s );
|
||||
operator fc::string()const;
|
||||
operator uint32_t()const;
|
||||
|
||||
friend bool operator==( const address& a, const address& b );
|
||||
private:
|
||||
uint32_t _ip;
|
||||
};
|
||||
|
|
@ -30,10 +32,13 @@ namespace fc {
|
|||
uint16_t port()const;
|
||||
const address& get_address()const;
|
||||
|
||||
friend bool operator==( const endpoint& a, const endpoint& b );
|
||||
|
||||
private:
|
||||
uint16_t _port;
|
||||
address _ip;
|
||||
};
|
||||
}
|
||||
}
|
||||
bool operator==( const fc::ip::endpoint& a, const fc::ip::endpoint& b );
|
||||
#endif // _FC_ENDPOINT_HPP_
|
||||
|
|
|
|||
148
include/fc/pke.hpp
Normal file
148
include/fc/pke.hpp
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
#ifndef FC_PKE_HPP_
|
||||
#define FC_PKE_HPP_
|
||||
#include <fc/sha1.hpp>
|
||||
#include <fc/vector.hpp>
|
||||
|
||||
/**
|
||||
* Define common crypto methods and data types to abstract underlying implementation.
|
||||
*/
|
||||
namespace fc {
|
||||
|
||||
template<uint32_t KeySize=2048>
|
||||
struct signature {
|
||||
char data[KeySize/8];
|
||||
template<typename T,uint32_t KS>
|
||||
friend T& operator<<( T& ds, const fc::signature<KS>& sig )
|
||||
{
|
||||
ds.write(sig.data, KS/8 );
|
||||
return ds;
|
||||
}
|
||||
template<typename T,uint32_t KS>
|
||||
friend T& operator>>( T& ds, fc::signature<KS>& sig )
|
||||
{
|
||||
ds.read(sig.data, KS/8 );
|
||||
return ds;
|
||||
}
|
||||
bool operator != ( const signature& s )const {
|
||||
return memcmp( s.data, data, sizeof(data) ) != 0;
|
||||
}
|
||||
bool operator == ( const signature& s )const {
|
||||
return memcmp( s.data, data, sizeof(data) ) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
bool verify_data( const char* key, uint32_t key_size, uint32_t pe, const sha1& hc, const char* sig );
|
||||
bool sign_data( const fc::vector<char>& key, uint32_t key_size, uint32_t pe, const sha1& hc, char* sig );
|
||||
bool public_encrypt( const char* key, uint32_t key_size, uint32_t pe, const fc::vector<char>& in, fc::vector<char>& out );
|
||||
bool public_decrypt( const char* key, uint32_t key_size, uint32_t pe, const fc::vector<char>& in, fc::vector<char>& out );
|
||||
bool private_encrypt( const fc::vector<char>& key, uint32_t key_size, uint32_t pe, const fc::vector<char>& in, fc::vector<char>& out );
|
||||
bool private_decrypt( const fc::vector<char>& key, uint32_t key_size, uint32_t pe, const fc::vector<char>& in, fc::vector<char>& out );
|
||||
bool generate_keys( char* pubkey, fc::vector<char>& privkey, uint32_t key_size, uint32_t pe );
|
||||
|
||||
template<uint32_t KeySize = 2048, uint32_t PublicExponent = 65537>
|
||||
struct private_key;
|
||||
|
||||
template<uint32_t KeySize = 2048, uint32_t PublicExponent = 65537>
|
||||
struct public_key {
|
||||
public_key() { memset( key, 0, sizeof(key) ); }
|
||||
public_key( const public_key& pk ) { memcpy( key, pk.key, sizeof(key) ); }
|
||||
|
||||
bool verify( const sha1& digest, const signature<KeySize>& sig )const {
|
||||
return verify_data( key, sizeof(key), PublicExponent, digest, sig.data );
|
||||
}
|
||||
bool encrypt( const fc::vector<char>& in, fc::vector<char>& out )const {
|
||||
return public_encrypt( key, KeySize, PublicExponent, in, out );
|
||||
}
|
||||
bool decrypt( const fc::vector<char>& in, fc::vector<char>& out )const {
|
||||
return public_decrypt( key, KeySize, PublicExponent, in, out );
|
||||
}
|
||||
|
||||
public_key& operator = ( const public_key& pk ) {
|
||||
memcpy( key, pk.key, sizeof(key) );
|
||||
return *this;
|
||||
}
|
||||
bool operator == ( const public_key& pk )const {
|
||||
return 0 == memcmp( key, pk.key, sizeof(key) );
|
||||
}
|
||||
bool operator != ( const public_key& pk )const {
|
||||
return 0 != memcmp( key, pk.key, sizeof(key) );
|
||||
}
|
||||
bool operator > ( const public_key& pk )const {
|
||||
return memcmp( key, pk.key, sizeof(key) ) > 0;
|
||||
}
|
||||
bool operator < ( const public_key& pk )const {
|
||||
return memcmp( key, pk.key, sizeof(key) ) < 0;
|
||||
}
|
||||
|
||||
template<typename T,uint32_t KS, uint32_t PE>
|
||||
inline friend T& operator<<( T& ds, const fc::public_key<KS,PE>& pk ) {
|
||||
ds.write(pk.key, KS/8 );
|
||||
return ds;
|
||||
}
|
||||
template<typename T,uint32_t KS, uint32_t PE>
|
||||
inline friend T& operator>>( T& ds, fc::public_key<KS,PE>& pk ) {
|
||||
ds.read( pk.key, KS/8 );
|
||||
return ds;
|
||||
}
|
||||
|
||||
private:
|
||||
template<uint32_t KS, uint32_t PE>
|
||||
friend void generate_keys( public_key<KS,PE>& pub, private_key<KS,PE>& priv );
|
||||
|
||||
char key[KeySize/8];
|
||||
};
|
||||
|
||||
|
||||
template<uint32_t KeySize, uint32_t PublicExponent>
|
||||
struct private_key {
|
||||
bool encrypt( const fc::vector<char>& in, fc::vector<char>& out )const {
|
||||
return private_encrypt( key, KeySize, PublicExponent, in, out );
|
||||
}
|
||||
bool decrypt( const fc::vector<char>& in, fc::vector<char>& out )const {
|
||||
return private_decrypt( key, KeySize, PublicExponent, in, out );
|
||||
}
|
||||
bool sign( const sha1& digest, signature<KeySize>& sig )const {
|
||||
return sign_data( key, KeySize, PublicExponent, digest, sig.data );
|
||||
}
|
||||
|
||||
template<typename T,uint32_t KS, uint32_t PE>
|
||||
friend T& operator<<( T& ds, const fc::private_key<KS,PE>& pk ) {
|
||||
ds << uint16_t(pk.key.size());
|
||||
ds.write( &pk.key.front(), pk.key.size() );
|
||||
return ds;
|
||||
}
|
||||
template<typename T,uint32_t KS, uint32_t PE>
|
||||
friend T& operator>>( T& ds, fc::private_key<KS,PE>& pk ) {
|
||||
uint16_t s;
|
||||
ds >> s;
|
||||
pk.key.resize(s);
|
||||
ds.read( &pk.key.front(), pk.key.size() );
|
||||
return ds;
|
||||
}
|
||||
private:
|
||||
template<uint32_t KS, uint32_t PE>
|
||||
friend void generate_keys( public_key<KS,PE>& pub, private_key<KS,PE>& priv );
|
||||
fc::vector<char> key;
|
||||
};
|
||||
|
||||
template<uint32_t KeySize, uint32_t PublicExponent>
|
||||
void generate_keys( public_key<KeySize,PublicExponent>& pub, private_key<KeySize,PublicExponent>& priv ) {
|
||||
generate_keys( pub.key, priv.key, KeySize, PublicExponent );
|
||||
}
|
||||
/*
|
||||
template<uint32_t KeySize>
|
||||
inline std::ostream& operator<< ( std::ostream& os, const signature<KeySize>& s ) {
|
||||
for( uint32_t i = 0; i < KeySize; ++i )
|
||||
os << std::hex << int(s.data[i]) << ' ';
|
||||
return os;
|
||||
}
|
||||
*/
|
||||
|
||||
typedef public_key<> public_key_t;
|
||||
typedef private_key<> private_key_t;
|
||||
typedef signature<> signature_t;
|
||||
|
||||
} // namespace fc
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -22,6 +22,7 @@ namespace fc {
|
|||
class encoder {
|
||||
public:
|
||||
encoder();
|
||||
~encoder();
|
||||
|
||||
void write( const char* d, uint32_t dlen );
|
||||
void reset();
|
||||
|
|
@ -29,18 +30,18 @@ namespace fc {
|
|||
|
||||
private:
|
||||
struct impl;
|
||||
fwd<impl,8> my;
|
||||
fwd<impl,89> my;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline friend T& operator<<( T& ds, const sha1& ep ) {
|
||||
ds.write( (const char*)ep.hash, sizeof(ep.hash) );
|
||||
ds.write( ep.data(), sizeof(ep) );
|
||||
return ds;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline friend T& operator>>( T& ds, sha1& ep ) {
|
||||
ds.read( (char*)ep.hash, sizeof(ep.hash) );
|
||||
ds.read( ep.data(), sizeof(ep) );
|
||||
return ds;
|
||||
}
|
||||
friend sha1 operator << ( const sha1& h1, uint32_t i );
|
||||
|
|
@ -49,6 +50,7 @@ namespace fc {
|
|||
friend sha1 operator ^ ( const sha1& h1, const sha1& h2 );
|
||||
friend bool operator >= ( const sha1& h1, const sha1& h2 );
|
||||
friend bool operator > ( const sha1& h1, const sha1& h2 );
|
||||
friend bool operator < ( const sha1& h1, const sha1& h2 );
|
||||
|
||||
uint32_t _hash[5];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -43,10 +43,11 @@ namespace fc {
|
|||
if( _ptr ) _ptr->release();
|
||||
}
|
||||
shared_ptr& reset( T* v = 0 ) {
|
||||
if( v == _ptr ) return;
|
||||
if( v == _ptr ) return *this;
|
||||
if( _ptr ) _ptr->release();
|
||||
_ptr = v;
|
||||
if( _ptr ) _ptr->retain();
|
||||
return *this;
|
||||
}
|
||||
|
||||
shared_ptr& operator=(const shared_ptr& p ) {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ namespace fc {
|
|||
|
||||
void reserve( uint64_t );
|
||||
uint64_t size()const;
|
||||
uint64_t find( char c, uint64_t pos = 0 )const;
|
||||
|
||||
void resize( uint64_t s );
|
||||
void clear();
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ namespace fc {
|
|||
friend class time_point;
|
||||
int64_t _count;
|
||||
};
|
||||
inline microseconds seconds( int64_t s ) { return microseconds( s * 1000000 ); }
|
||||
|
||||
class time_point {
|
||||
public:
|
||||
|
|
|
|||
30
include/fc/udp_socket.hpp
Normal file
30
include/fc/udp_socket.hpp
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef _FC_UDP_SOCKET_HPP_
|
||||
#define _FC_UDP_SOCKET_HPP_
|
||||
#include <fc/utility.hpp>
|
||||
#include <fc/fwd.hpp>
|
||||
|
||||
namespace fc {
|
||||
namespace ip {
|
||||
class endpoint;
|
||||
}
|
||||
|
||||
class udp_socket {
|
||||
public:
|
||||
udp_socket();
|
||||
~udp_socket();
|
||||
|
||||
void open();
|
||||
void set_receive_buffer_size( size_t s );
|
||||
void bind( const fc::ip::endpoint& );
|
||||
size_t receive_from( char* b, size_t l, fc::ip::endpoint& from );
|
||||
size_t send_to( const char* b, size_t l, const fc::ip::endpoint& to );
|
||||
void close();
|
||||
|
||||
private:
|
||||
class impl;
|
||||
fwd<impl,32> my;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -49,7 +49,7 @@ namespace fc {
|
|||
vector_impl( vector_impl&& c):_data(c._data){c._data =nullptr; }
|
||||
vector_impl( const vector_impl& c):_data(nullptr) {
|
||||
if( c.size() ) {
|
||||
_data = data<T>::allocate( c.size() );
|
||||
_data = detail::data<T>::allocate( c.size() );
|
||||
memcpy(begin(),c.begin(),c.size() );
|
||||
}
|
||||
}
|
||||
|
|
@ -70,6 +70,8 @@ namespace fc {
|
|||
const T& back()const { return (&_data->first)[-1+_data->size]; }
|
||||
T& front() { return (&_data->first)[0]; }
|
||||
const T& front()const { return (&_data->first)[0]; }
|
||||
const T* data()const { return (&_data->first); }
|
||||
T* data() { return (&_data->first); }
|
||||
|
||||
iterator begin() { return _data ? &front() : 0;}
|
||||
const_iterator begin()const { return _data ? &front() : 0;}
|
||||
|
|
@ -90,12 +92,12 @@ namespace fc {
|
|||
}
|
||||
|
||||
void reserve( uint64_t i ) {
|
||||
_data = data<T>::reallocate( _data, i );
|
||||
_data = detail::data<T>::reallocate( _data, i );
|
||||
}
|
||||
|
||||
void resize( uint64_t i ) {
|
||||
if( capacity() < i )
|
||||
_data = data<T>::reallocate( _data, i );
|
||||
_data = detail::data<T>::reallocate( _data, i );
|
||||
_data->size = i;
|
||||
}
|
||||
|
||||
|
|
@ -154,7 +156,7 @@ namespace fc {
|
|||
return *this;
|
||||
}
|
||||
protected:
|
||||
data<T>* _data;
|
||||
detail::data<T>* _data;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -164,7 +166,7 @@ namespace fc {
|
|||
vector_impl( vector_impl&& c):_data(c._data){c._data =nullptr; }
|
||||
vector_impl( const vector_impl& c):_data(nullptr) {
|
||||
if( c.size() ) {
|
||||
_data = data<T>::allocate( c.size() );
|
||||
_data = detail::data<T>::allocate( c.size() );
|
||||
auto i = begin();
|
||||
auto ci = c.begin();
|
||||
auto ce = c.end();
|
||||
|
|
@ -194,6 +196,8 @@ namespace fc {
|
|||
const T& back()const { return (&_data->first)[-1+_data->size]; }
|
||||
T& front() { return (&_data->first)[0]; }
|
||||
const T& front()const { return (&_data->first)[0]; }
|
||||
const T* data()const { return (&_data->first); }
|
||||
T* data() { return (&_data->first); }
|
||||
|
||||
iterator begin() { return _data ? &front() : 0;}
|
||||
const_iterator begin()const { return _data ? &front() : 0;}
|
||||
|
|
@ -225,7 +229,7 @@ namespace fc {
|
|||
if( nullptr != this->_data && i <= this->_data->capacity )
|
||||
return;
|
||||
|
||||
auto _ndata = data<T>::allocate( i );
|
||||
auto _ndata = detail::data<T>::allocate( i );
|
||||
auto nc = &_ndata->first;
|
||||
auto c = this->begin();
|
||||
auto e = this->end();
|
||||
|
|
@ -319,7 +323,7 @@ namespace fc {
|
|||
return *this;
|
||||
}
|
||||
private:
|
||||
data<T>* _data;
|
||||
detail::data<T>* _data;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
138
src/base64.cpp
Normal file
138
src/base64.cpp
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
#include <fc/base64.hpp>
|
||||
#include <ctype.h>
|
||||
/*
|
||||
base64.cpp and base64.h
|
||||
|
||||
Copyright (C) 2004-2008 René Nyffenegger
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the author be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
René Nyffenegger rene.nyffenegger@adp-gmbh.ch
|
||||
|
||||
*/
|
||||
|
||||
namespace fc {
|
||||
|
||||
inline const fc::string& base64_chars()
|
||||
{
|
||||
static const fc::string m_base64_chars =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
return m_base64_chars;
|
||||
}
|
||||
|
||||
static inline bool is_base64(unsigned char c) {
|
||||
return (isalnum(c) || (c == '+') || (c == '/'));
|
||||
}
|
||||
|
||||
fc::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len);
|
||||
|
||||
fc::string base64_encode( const fc::string& enc ) {
|
||||
char const* s = enc.c_str();
|
||||
return base64_encode( (unsigned char const*)s, enc.size() );
|
||||
}
|
||||
fc::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
|
||||
|
||||
fc::string ret;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
unsigned char char_array_3[3];
|
||||
unsigned char char_array_4[4];
|
||||
|
||||
while (in_len--) {
|
||||
char_array_3[i++] = *(bytes_to_encode++);
|
||||
if (i == 3) {
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for(i = 0; (i <4) ; i++)
|
||||
ret += base64_chars()[char_array_4[i]];
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i)
|
||||
{
|
||||
for(j = i; j < 3; j++)
|
||||
char_array_3[j] = '\0';
|
||||
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for (j = 0; (j < i + 1); j++)
|
||||
ret += base64_chars()[char_array_4[j]];
|
||||
|
||||
while((i++ < 3))
|
||||
ret += '=';
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
fc::string base64_decode(fc::string const& encoded_string) {
|
||||
int in_len = encoded_string.size();
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int in_ = 0;
|
||||
unsigned char char_array_4[4], char_array_3[3];
|
||||
fc::string ret;
|
||||
|
||||
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
|
||||
char_array_4[i++] = encoded_string[in_]; in_++;
|
||||
if (i ==4) {
|
||||
for (i = 0; i <4; i++)
|
||||
char_array_4[i] = base64_chars().find(char_array_4[i]);
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
|
||||
for (i = 0; (i < 3); i++)
|
||||
ret += char_array_3[i];
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i) {
|
||||
for (j = i; j <4; j++)
|
||||
char_array_4[j] = 0;
|
||||
|
||||
for (j = 0; j <4; j++)
|
||||
char_array_4[j] = base64_chars().find(char_array_4[j]);
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
|
||||
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace fc
|
||||
|
||||
10
src/ip.cpp
10
src/ip.cpp
|
|
@ -12,6 +12,10 @@ namespace fc { namespace ip {
|
|||
_ip = boost::asio::ip::address_v4::from_string(s.c_str()).to_ulong();
|
||||
}
|
||||
|
||||
bool operator==( const address& a, const address& b ) {
|
||||
return uint32_t(a) == uint32_t(b);
|
||||
}
|
||||
|
||||
address& address::operator=( const fc::string& s ) {
|
||||
_ip = boost::asio::ip::address_v4::from_string(s.c_str()).to_ulong();
|
||||
return *this;
|
||||
|
|
@ -20,6 +24,9 @@ namespace fc { namespace ip {
|
|||
address::operator fc::string()const {
|
||||
return boost::asio::ip::address_v4(_ip).to_string().c_str();
|
||||
}
|
||||
address::operator uint32_t()const {
|
||||
return _ip;
|
||||
}
|
||||
|
||||
|
||||
endpoint::endpoint()
|
||||
|
|
@ -27,6 +34,9 @@ namespace fc { namespace ip {
|
|||
endpoint::endpoint(const address& a, uint16_t p)
|
||||
:_port(p),_ip(a){}
|
||||
|
||||
bool operator==( const endpoint& a, const endpoint& b ) {
|
||||
return a._port == b._port && a._ip == b._ip;
|
||||
}
|
||||
uint16_t endpoint::port()const { return _port; }
|
||||
const address& endpoint::get_address()const { return _ip; }
|
||||
|
||||
|
|
|
|||
141
src/pke.cpp
Normal file
141
src/pke.cpp
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
#include <fc/pke.hpp>
|
||||
#include <fc/error.hpp>
|
||||
#include <fc/exception.hpp>
|
||||
#include <iostream>
|
||||
#include <fc/sha1.hpp>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
namespace fc {
|
||||
RSA* get_pub( const char* key, uint32_t key_size, uint32_t pe )
|
||||
{
|
||||
RSA* rsa = RSA_new();
|
||||
rsa->n = BN_bin2bn( (unsigned char*)key, key_size, NULL );
|
||||
rsa->e = BN_new();
|
||||
BN_set_word(rsa->e, pe );
|
||||
return rsa;
|
||||
}
|
||||
RSA* get_priv( const fc::vector<char>& d, uint32_t /*key_size*/, uint32_t /*pe*/ )
|
||||
{
|
||||
BIO* mem = (BIO*)BIO_new_mem_buf( (void*)&d.front(), d.size() );
|
||||
RSA* rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, NULL, NULL );
|
||||
BIO_free(mem);
|
||||
return rsa;
|
||||
}
|
||||
|
||||
bool verify_data( const char* key, uint32_t key_size, uint32_t pe, const sha1& digest, const char* sig )
|
||||
{
|
||||
RSA* pub = get_pub( key,key_size,pe);
|
||||
bool v = RSA_verify( NID_sha1, (const uint8_t*)digest.data(), 20, (uint8_t*)sig, key_size, pub );
|
||||
RSA_free(pub);
|
||||
return v;
|
||||
}
|
||||
bool sign_data( const fc::vector<char>& key, uint32_t key_size, uint32_t pe, const sha1& digest, char* sig )
|
||||
{
|
||||
RSA* priv = get_priv( key,key_size,pe);
|
||||
if( !priv ) {
|
||||
generic_exception g(fc::generic_exception("Error loading private key: " + fc::string(ERR_error_string( ERR_get_error(),NULL))) );
|
||||
FC_THROW(g);
|
||||
}
|
||||
uint32_t slen = 0;
|
||||
if( 1 != RSA_sign( NID_sha1, (uint8_t*)digest.data(), sizeof(digest), (unsigned char*)sig, &slen, priv ) )
|
||||
{
|
||||
RSA_free(priv);
|
||||
generic_exception g(fc::generic_exception("Error signing data: " + fc::string(ERR_error_string( ERR_get_error(),NULL))) );
|
||||
FC_THROW(g);
|
||||
|
||||
}
|
||||
RSA_free(priv);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool public_encrypt( const char* key, uint32_t key_size, uint32_t pe, const fc::vector<char>& in, fc::vector<char>& out )
|
||||
{
|
||||
RSA* pub = get_pub( key,key_size/8,pe);
|
||||
out.resize(RSA_size(pub));
|
||||
int rtn = RSA_public_encrypt( in.size(), (unsigned char*)&in.front(), (unsigned char*)&out.front(), pub, RSA_PKCS1_OAEP_PADDING );
|
||||
RSA_free(pub);
|
||||
if( rtn >= 0 )
|
||||
{
|
||||
out.resize(rtn);
|
||||
return true;
|
||||
}
|
||||
out.resize(0);
|
||||
FC_THROW( fc::generic_exception( ERR_error_string( ERR_get_error(), NULL ) ) );
|
||||
return false;
|
||||
}
|
||||
bool public_decrypt( const char* key, uint32_t key_size, uint32_t pe, const fc::vector<char>& in, fc::vector<char>& out )
|
||||
{
|
||||
RSA* pub = get_pub( key,key_size/8,pe);
|
||||
out.resize(RSA_size(pub));
|
||||
int rtn = RSA_public_decrypt( RSA_size(pub), (unsigned char*)&in.front(), (unsigned char*)&out.front(), pub, RSA_PKCS1_OAEP_PADDING );
|
||||
RSA_free(pub);
|
||||
if( rtn >= 0 )
|
||||
{
|
||||
out.resize(rtn);
|
||||
return true;
|
||||
}
|
||||
out.resize(0);
|
||||
FC_THROW( fc::generic_exception( ERR_error_string( ERR_get_error(), NULL ) ) );
|
||||
return false;;
|
||||
}
|
||||
bool private_encrypt( const fc::vector<char>& key, uint32_t key_size, uint32_t pe, const fc::vector<char>& in, fc::vector<char>& out )
|
||||
{
|
||||
RSA* priv = get_priv( key,key_size/8,pe);
|
||||
int rtn = RSA_private_encrypt( in.size(), (unsigned char*)&in.front(), (unsigned char*)&out.front(), priv, RSA_PKCS1_OAEP_PADDING );
|
||||
RSA_free(priv);
|
||||
if( rtn >= 0 )
|
||||
{
|
||||
out.resize(rtn);
|
||||
return true;
|
||||
}
|
||||
out.resize(0);
|
||||
return false;;
|
||||
}
|
||||
bool private_decrypt( const fc::vector<char>& key, uint32_t key_size, uint32_t pe, const fc::vector<char>& in, fc::vector<char>& out )
|
||||
{
|
||||
|
||||
RSA* priv = get_priv( key,key_size/8,pe);
|
||||
out.resize(RSA_size(priv));
|
||||
int rtn = RSA_private_decrypt( in.size(), (unsigned char*)&in.front(), (unsigned char*)&out.front(), priv, RSA_PKCS1_OAEP_PADDING );
|
||||
RSA_free(priv);
|
||||
if( rtn >= 0 )
|
||||
{
|
||||
out.resize(rtn);
|
||||
return true;
|
||||
}
|
||||
out.resize(0);
|
||||
FC_THROW( fc::generic_exception( ERR_error_string( ERR_get_error(), NULL ) ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
bool generate_keys( char* pubkey, fc::vector<char>& privkey, uint32_t key_size, uint32_t pe )
|
||||
{
|
||||
static bool init = true;
|
||||
if( init ) { ERR_load_crypto_strings(); init = false; }
|
||||
|
||||
RSA* rsa = RSA_generate_key( key_size, pe, NULL, NULL );
|
||||
BN_bn2bin( rsa->n, (unsigned char*)pubkey );
|
||||
|
||||
BIO *mem = BIO_new(BIO_s_mem());
|
||||
int e = PEM_write_bio_RSAPrivateKey(mem, rsa, NULL, NULL, 0, NULL, NULL );
|
||||
if( e != 1 )
|
||||
{
|
||||
BIO_free(mem);
|
||||
RSA_free(rsa);
|
||||
FC_THROW(generic_exception("Error writing PrivateKey") );
|
||||
}
|
||||
|
||||
char* dat;
|
||||
uint32_t l = BIO_get_mem_data( mem, &dat );
|
||||
privkey.resize(l);
|
||||
memcpy( &privkey.front(), dat, l );
|
||||
|
||||
BIO_free(mem);
|
||||
RSA_free(rsa);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@ namespace fc {
|
|||
SHA_CTX ctx;
|
||||
};
|
||||
|
||||
sha1::encoder::~encoder() {}
|
||||
sha1::encoder::encoder() {
|
||||
reset();
|
||||
}
|
||||
|
|
@ -72,6 +73,9 @@ namespace fc {
|
|||
bool operator > ( const fc::sha1& h1, const fc::sha1& h2 ) {
|
||||
return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) > 0;
|
||||
}
|
||||
bool operator < ( const fc::sha1& h1, const fc::sha1& h2 ) {
|
||||
return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) < 0;
|
||||
}
|
||||
bool operator != ( const fc::sha1& h1, const fc::sha1& h2 ) {
|
||||
return memcmp( h1._hash, h2._hash, sizeof(h1._hash) ) != 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ namespace fc {
|
|||
|
||||
void string::reserve(uint64_t r) { reinterpret_cast<std::string*>(this)->reserve(r); }
|
||||
uint64_t string::size()const { return reinterpret_cast<const std::string*>(this)->size(); }
|
||||
uint64_t string::find(char c, uint64_t p)const { return reinterpret_cast<const std::string*>(this)->find(c,p); }
|
||||
void string::clear() { return reinterpret_cast<std::string*>(this)->clear(); }
|
||||
void string::resize( uint64_t s ) { reinterpret_cast<std::string*>(this)->resize(s); }
|
||||
|
||||
|
|
|
|||
81
src/udp_socket.cpp
Normal file
81
src/udp_socket.cpp
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
#include <fc/udp_socket.hpp>
|
||||
#include <fc/ip.hpp>
|
||||
#include <fc/fwd_impl.hpp>
|
||||
#include <fc/asio.hpp>
|
||||
|
||||
|
||||
namespace fc {
|
||||
|
||||
class udp_socket::impl {
|
||||
public:
|
||||
impl():_sock( fc::asio::default_io_service() ){}
|
||||
|
||||
boost::asio::ip::udp::socket _sock;
|
||||
};
|
||||
|
||||
boost::asio::ip::udp::endpoint to_asio_ep( const fc::ip::endpoint& e ) {
|
||||
return boost::asio::ip::udp::endpoint(boost::asio::ip::address_v4(e.get_address()), e.port() );
|
||||
}
|
||||
fc::ip::endpoint to_fc_ep( const boost::asio::ip::udp::endpoint& e ) {
|
||||
return fc::ip::endpoint( e.address().to_v4().to_ulong(), e.port() );
|
||||
}
|
||||
|
||||
udp_socket::udp_socket() {
|
||||
}
|
||||
udp_socket::~udp_socket() {
|
||||
}
|
||||
|
||||
size_t udp_socket::send_to( const char* b, size_t l, const ip::endpoint& to ) {
|
||||
try {
|
||||
return my->_sock.send_to( boost::asio::buffer(b, l), to_asio_ep(to) );
|
||||
} catch( const boost::system::system_error& e ) {
|
||||
if( e.code() == boost::asio::error::would_block ) {
|
||||
promise<size_t>::ptr p(new promise<size_t>("udp_socket::send_to"));
|
||||
my->_sock.async_send_to( boost::asio::buffer(b,l), to_asio_ep(to),
|
||||
[=]( const boost::system::error_code& ec, size_t bt ) {
|
||||
if( !ec ) p->set_value(bt);
|
||||
else p->set_exception( fc::copy_exception( boost::system::system_error(ec) ) );
|
||||
});
|
||||
return p->wait();
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
void udp_socket::open() {
|
||||
my->_sock.open( boost::asio::ip::udp::v4() );
|
||||
my->_sock.non_blocking(true);
|
||||
}
|
||||
void udp_socket::set_receive_buffer_size( size_t s ) {
|
||||
my->_sock.set_option(boost::asio::socket_base::receive_buffer_size(s) );
|
||||
}
|
||||
void udp_socket::bind( const fc::ip::endpoint& e ) {
|
||||
my->_sock.bind( to_asio_ep(e) );
|
||||
}
|
||||
size_t udp_socket::receive_from( char* b, size_t l, fc::ip::endpoint& _from ) {
|
||||
try {
|
||||
boost::asio::ip::udp::endpoint from;
|
||||
size_t r = my->_sock.receive_from( boost::asio::buffer(b, l), from );
|
||||
_from = to_fc_ep(from);
|
||||
return r;
|
||||
} catch( const boost::system::system_error& e ) {
|
||||
if( e.code() == boost::asio::error::would_block ) {
|
||||
boost::asio::ip::udp::endpoint from;
|
||||
promise<size_t>::ptr p(new promise<size_t>("udp_socket::send_to"));
|
||||
my->_sock.async_receive_from( boost::asio::buffer(b,l), from,
|
||||
[=]( const boost::system::error_code& ec, size_t bt ) {
|
||||
if( !ec ) p->set_value(bt);
|
||||
else p->set_exception( fc::copy_exception( boost::system::system_error(ec) ) );
|
||||
});
|
||||
auto r = p->wait();
|
||||
_from = to_fc_ep(from);
|
||||
return r;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
void udp_socket::close() {
|
||||
my->_sock->cancel();
|
||||
my->_sock.close();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in a new issue