moving more functions from mace to fc

This commit is contained in:
Daniel Larimer 2012-09-08 23:46:19 -04:00
parent 460da34801
commit 018609fafa
21 changed files with 746 additions and 32 deletions

View file

@ -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} )

View file

@ -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
View 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
View 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

View file

@ -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"; }
};

View file

@ -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& );

View file

@ -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) );
}

View file

@ -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;
};
@ -29,6 +31,8 @@ namespace fc {
uint16_t port()const;
const address& get_address()const;
friend bool operator==( const endpoint& a, const endpoint& b );
private:
uint16_t _port;
@ -36,4 +40,5 @@ namespace fc {
};
}
}
bool operator==( const fc::ip::endpoint& a, const fc::ip::endpoint& b );
#endif // _FC_ENDPOINT_HPP_

148
include/fc/pke.hpp Normal file
View 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

View file

@ -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];
};

View file

@ -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 ) {

View file

@ -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();

View file

@ -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
View 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

View file

@ -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() );
}
}
@ -69,7 +69,9 @@ namespace fc {
T& back() { return (&_data->first)[-1+_data->size]; }
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& 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
View 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

View file

@ -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
View 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;
}
}

View file

@ -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;
}

View file

@ -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
View 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();
}
}