Separated ana.hpp & detail.hpp into several single-purpose files...

...and updated error_code creation to comply with boost 1.35.
This commit is contained in:
Guillermo Biset 2010-06-10 23:18:14 +00:00
parent 8a310769d7
commit 83f105b6b3
11 changed files with 876 additions and 728 deletions

View file

@ -51,13 +51,10 @@
*
* @section requirements requirements
* To compile ana, you need:
* - Boost, version 1.37 or older
* - Boost, version 1.35 or older
*
*/
#ifndef ANA_HPP
#define ANA_HPP
#include <boost/cstdint.hpp>
#include <boost/noncopyable.hpp>
#include <boost/system/error_code.hpp>
@ -68,184 +65,22 @@
#include <cstdlib>
#include <ctime>
#ifndef ANA_HPP
#define ANA_HPP
#define ANA_DETAIL_INTERNAL_HPP
#include "common.hpp" //Main definitions
#include "timers.hpp" //Timer related
#include "predicates.hpp" //Client predicates, used for conditional sending
#include "binary_streams.hpp" //For serialization
#undef ANA_DETAIL_INTERNAL_HPP
/** @namespace ana
*
* Namespace for project ana, the entire API is under this namespce.
*/
namespace ana
{
/** @name Type and constant definitions
*
* Definitions of main types and relevant constants.
*/
//@{
typedef uint32_t ana_uint32 /** Standard unsigned int, with fixed size to 32 bits. */ ;
typedef int32_t ana_int32 /** Standard int, with fixed size to 32 bits. */ ;
typedef ana_uint32 client_id /** Type of IDs of connected components, unique. */ ;
typedef ana_uint32 message_size /** Message size type. */ ;
typedef std::string port /** Port type, a std::string (instead of a short.) */ ;
typedef std::string address /** Address type, a string. Either IP of hostname. */ ;
typedef bool send_type /** Send operation type, true to copy the buffer. */ ;
typedef boost::system::error_code error_code /** Standard error code, can evaluate to bool. */ ;
const send_type ZeroCopy = false /** Don't copy the buffer. */ ;
const send_type CopyBuffer = true /** Copy the buffer. */ ;
const message_size HeaderLength = sizeof(ana_uint32) /** Length of message header. */ ;
const client_id ServerID = 0 /** The ID of the server application. */ ;
/**
* Timeout policies for send operations.
*
* \sa timer
*/
enum timeout_policy
{
NoTimeouts /** Don't use timers in any operation. */,
FixedTime /** Use timers with a fixed time for every operation. */,
TimePerKilobyte /** Use timers, calculating the necessary time from
the size of the buffer that is to be sent. */
};
//@}
/** @name Predicates over client ids.
*
* Declaration of types used in conditional send operations, e.g. send_if.
* \sa send_if
*/
//@{
/** A boolean predicate of client IDs. Used for conditional send operations. */
struct client_predicate
{
/**
* Decides if a given condition applies to a client.
*
* @param client ID of the queried client.
* @returns true if the condition holds for this client.
*/
virtual bool selects(client_id) const = 0;
};
//@}
/** @name Timers
*
* Definitions of timer related types.
*/
//@{
/**
* General purpose asynchronous timer.
*/
class timer
{
public:
/** Standard constructor. */
timer() :
io_service_(),
timer_(io_service_)
{
}
/**
* Wait in background a given amount of milliseconds.
*
* The method shouldn't be called with a size_t constant
* directly. Instead, the user should use the functions in
* the ana::time namespace.
*
* @param milliseconds : Amount of milliseconds to wait.
* @param handler : Handler object to handle the timeout event.
*
* Examples:
* - wait( ana::time::seconds(5),
* boost::bind( &ChatServer::handle_timeout, this,
* boost::asio::placeholders::error);
*
* \sa ana::time
*/
template<class Handler>
void wait(size_t milliseconds, Handler handler)
{
timer_.expires_from_now(milliseconds / 1000);
timer_.async_wait(handler);
boost::thread t( boost::bind( &boost::asio::io_service::run_one, &io_service_ ) );
}
/** Cancel the timer if running. */
void cancel()
{
timer_.cancel();
}
/** Standard destructor, cancels pending operations and stops the I/O service. */
~timer()
{
timer_.cancel();
io_service_.stop();
}
private:
/** Private class providing traits for the timer type. */
struct time_t_traits
{
// The time type.
typedef std::time_t time_type;
// The duration type.
struct duration_type
{
duration_type() : value(0) {}
duration_type(std::time_t v) : value(v) {}
std::time_t value;
};
// Get the current time.
static time_type now()
{
return std::time(0);
}
// Add a duration to a time.
static time_type add(const time_type& t, const duration_type& d)
{
return t + d.value;
}
// Subtract one time from another.
static duration_type subtract(const time_type& t1, const time_type& t2)
{
return duration_type(t1 - t2);
}
// Test whether one time is less than another.
static bool less_than(const time_type& t1, const time_type& t2)
{
return t1 < t2;
}
// Convert to POSIX duration type.
static boost::posix_time::time_duration to_posix_duration(const duration_type& d)
{
return boost::posix_time::seconds(d.value);
}
};
boost::asio::io_service io_service_;
boost::asio::basic_deadline_timer<std::time_t,time_t_traits> timer_;
};
#define DETAIL_INTERNAL_HPP
#include "detail.hpp"
#undef DETAIL_INTERNAL_HPP
#include "binary_streams.hpp"
/** @name Handler Interfaces
*
* Interfaces to handle network events.
@ -286,6 +121,42 @@ namespace ana
virtual void handle_disconnect(error_code, client_id) = 0;
};
/** Used for implementation purposes. */
namespace detail
{
/**
* Base class for any network entity that handles incoming messages.
*/
class listener
{
public:
/**
* Sets the handler for incoming messages.
*
* @param listener : Pointer to the listener_handler object that will
* handle following incoming message events.
*
* \sa listener_handler
*/
virtual void set_listener_handler( listener_handler* listener ) = 0;
/**
* Get the client_id of this listener.
*
* @returns : ServerID for the server application, or a comparable client_id
* unique to this listener.
*
* \sa ServerID
* \sa client_id
*/
virtual client_id id() const = 0;
protected: // should be so?
/** Start listening for incoming messages. */
virtual void run_listener() = 0;
};
} //namespace details
/**
* Class that should be implemented to handle new connection events.
*/
@ -325,61 +196,6 @@ namespace ana
};
//@}
namespace detail
{
/**
* Base class for any network entity that handles incoming messages.
*/
class listener
{
public:
/**
* Sets the handler for incoming messages.
*
* @param listener : Pointer to the listener_handler object that will
* handle following incoming message events.
*
* \sa listener_handler
*/
virtual void set_listener_handler( listener_handler* listener ) = 0;
/**
* Get the client_id of this listener.
*
* @returns : ServerID for the server application, or a comparable client_id
* unique to this listener.
*
* \sa ServerID
* \sa client_id
*/
virtual client_id id() const = 0;
protected: // should be so?
/** Start listening for incoming messages. */
virtual void run_listener() = 0;
};
}
/**
* Creates a client predicate to be used in send operations.
*
* This function can be used to create predicate objects from the standard library's
* bind1st objects and from boost::bind too.
*
* Examples:
* - server_->send_if(boost::asio::buffer( str ), this, create_predicate(
* boost::bind( std::not_equal_to<client_id>(), client, _1) ) );
*
* @param pred Predicate of the queried client.
* @returns Predicate for client selection.
*/
template<class predicate>
detail::_generic_client_predicate<predicate> create_predicate(const predicate& pred)
{
return detail::_generic_client_predicate<predicate>(pred);
}
/** @name Time duration functions. */
//@{
/** @namespace time
@ -654,150 +470,6 @@ namespace ana
virtual ~client() {}
};
//@}
/** @name Buffer creation methods
*
* @defgroup buffer
*
* API user should create buffers with one of these methods.
*
* Paraphrasing boost asio's documentation on the buffer function:
* The ana::buffer function is used to create a buffer object to represent raw memory,
* an array of POD elements, a vector of POD elements, or a std::string.
*
* Check <http://think-async.com/Asio/boost_asio_1_3_1/doc/html/boost_asio/reference/buffer.html>
*/
//@{
inline boost::asio::mutable_buffers_1 buffer(const boost::asio::mutable_buffer & b)
{
return boost::asio::buffer(b);
}
inline boost::asio::mutable_buffers_1 buffer(const boost::asio::mutable_buffer & b, std::size_t max_size_in_bytes)
{
return boost::asio::buffer(b, max_size_in_bytes);
}
inline boost::asio::const_buffers_1 buffer(const boost::asio::const_buffer & b)
{
return boost::asio::buffer(b);
}
inline boost::asio::const_buffers_1 buffer(const boost::asio::const_buffer & b, std::size_t max_size_in_bytes)
{
return boost::asio::buffer(b, max_size_in_bytes);
}
inline boost::asio::mutable_buffers_1 buffer(void * data, std::size_t size_in_bytes)
{
return boost::asio::buffer(data, size_in_bytes);
}
inline boost::asio::const_buffers_1 buffer(const void * data, std::size_t size_in_bytes)
{
return boost::asio::buffer(data, size_in_bytes);
}
template<typename PodType, std::size_t N>
inline boost::asio::mutable_buffers_1 buffer(PodType & data)
{
return boost::asio::buffer(data);
}
template<typename PodType, std::size_t N>
inline boost::asio::mutable_buffers_1 buffer(PodType & data, std::size_t max_size_in_bytes)
{
return boost::asio::buffer(data, max_size_in_bytes);
}
template<typename PodType, std::size_t N>
inline boost::asio::const_buffers_1 buffer(const PodType & data)
{
return boost::asio::buffer(data);
}
template<typename PodType, std::size_t N>
inline boost::asio::const_buffers_1 buffer(const PodType & data, std::size_t max_size_in_bytes)
{
return boost::asio::buffer(data, max_size_in_bytes);
}
template<typename PodType, std::size_t N>
inline boost::asio::mutable_buffers_1 buffer(boost::array< PodType, N > & data)
{
return boost::asio::buffer(data);
}
template<typename PodType, std::size_t N>
inline boost::asio::mutable_buffers_1 buffer(boost::array< PodType, N > & data,
std::size_t max_size_in_bytes)
{
return boost::asio::buffer(data, max_size_in_bytes);
}
template<typename PodType, std::size_t N>
inline boost::asio::const_buffers_1 buffer(boost::array< const PodType, N > & data)
{
return boost::asio::buffer(data);
}
template<typename PodType, std::size_t N>
inline boost::asio::const_buffers_1 buffer(boost::array< const PodType, N > & data,
std::size_t max_size_in_bytes)
{
return boost::asio::buffer(data, max_size_in_bytes);
}
template<typename PodType, std::size_t N>
inline boost::asio::const_buffers_1 buffer(const boost::array< PodType, N > & data)
{
return boost::asio::buffer(data);
}
template<typename PodType, std::size_t N>
inline boost::asio::const_buffers_1 buffer(const boost::array< PodType, N > & data,
std::size_t max_size_in_bytes)
{
return boost::asio::buffer(data, max_size_in_bytes);
}
template<typename PodType, typename Allocator>
inline boost::asio::mutable_buffers_1 buffer(std::vector< PodType, Allocator > & data)
{
return boost::asio::buffer(data);
}
template<typename PodType, typename Allocator>
inline boost::asio::mutable_buffers_1 buffer(std::vector< PodType, Allocator > & data,
std::size_t max_size_in_bytes)
{
return boost::asio::buffer(data, max_size_in_bytes);
}
template<typename PodType, typename Allocator>
inline boost::asio::const_buffers_1 buffer(const std::vector< PodType, Allocator > & data)
{
return boost::asio::buffer(data);
}
template<typename PodType, typename Allocator>
inline boost::asio::const_buffers_1 buffer(const std::vector< PodType, Allocator > & data,
std::size_t max_size_in_bytes)
{
return boost::asio::buffer(data, max_size_in_bytes);
}
inline boost::asio::const_buffers_1 buffer(const std::string & data)
{
return boost::asio::buffer(data);
}
inline boost::asio::const_buffers_1 buffer(const std::string & data, std::size_t max_size_in_bytes)
{
return boost::asio::buffer(data, max_size_in_bytes);
}
//@}
}
#endif

View file

@ -40,123 +40,127 @@
#include <assert.h>
#include <stdint.h>
namespace serializer
namespace ana
{
class bostream
namespace serializer
{
public:
bostream() :
_s()
{
}
class bostream
{
public:
bostream() :
_s()
{
}
template <class T>
bostream& operator<< (T x)
{
_s.append(reinterpret_cast<char*>(&x), sizeof(T));
return *this;
}
template <class T>
bostream& operator<< (T x)
{
_s.append(reinterpret_cast<char*>(&x), sizeof(T));
return *this;
}
/* Inserting a string inserts its size first. */
bostream& operator<< (const std::string& s)
{
(*this) << uint32_t( s.size() );
_s += s;
return *this;
}
/* Inserting a string inserts its size first. */
bostream& operator<< (const std::string& s)
{
(*this) << uint32_t( s.size() );
_s += s;
return *this;
}
template <class Other>
bostream& operator<< (const std::vector<Other>& vec)
{
const uint32_t size(vec.size());
(*this) << size;
for (size_t i(0); i < size; ++i)
(*this) << vec[i];
template <class Other>
bostream& operator<< (const std::vector<Other>& vec)
{
const uint32_t size(vec.size());
(*this) << size;
for (size_t i(0); i < size; ++i)
(*this) << vec[i];
return *this;
}
return *this;
}
bostream& operator<< (const char* cs)
{
const std::string s(cs);
return operator<< (s);
}
bostream& operator<< (const char* cs)
{
const std::string s(cs);
return operator<< (s);
}
const std::string& str() const
{
return _s;
}
const std::string& str() const
{
return _s;
}
void clear()
{
_s.clear();
}
void clear()
{
_s.clear();
}
private:
std::string _s;
};
private:
std::string _s;
};
class bistream
{
public:
bistream(const std::string& str) :
_s(str),
_pos(0)
{
}
class bistream
{
public:
bistream(const std::string& str) :
_s(str),
_pos(0)
{
}
bistream() :
_s(),
_pos(0)
{
}
bistream() :
_s(),
_pos(0)
{
}
void str(const std::string& str)
{
_pos = 0;
_s = str;
}
void str(const std::string& str)
{
_pos = 0;
_s = str;
}
template <class T>
bistream& operator >> (T& x)
{
assert(_s.size() >= _pos + sizeof(x));
_pos += _s.copy(reinterpret_cast<char*>(&x), sizeof(x),_pos);
return *this;
}
template <class T>
bistream& operator >> (T& x)
{
assert(_s.size() >= _pos + sizeof(x));
_pos += _s.copy(reinterpret_cast<char*>(&x), sizeof(x),_pos);
return *this;
}
bistream& operator >> (std::string& str)
{
uint32_t size;
(*this) >> size;
assert(_s.size() >= size+_pos);
str = _s.substr(_pos,size);
_pos += size;
return *this;
}
bistream& operator >> (std::string& str)
{
uint32_t size;
(*this) >> size;
assert(_s.size() >= size+_pos);
str = _s.substr(_pos,size);
_pos += size;
return *this;
}
template <class Other>
bistream& operator>> (std::vector<Other>& vec)
{
uint32_t size;
(*this) >> size;
assert(_s.size() >= (size * sizeof(Other)) + _pos);
vec.resize(size);
for (size_t i(0); i < size; i++)
(*this) >> vec[i];
template <class Other>
bistream& operator>> (std::vector<Other>& vec)
{
uint32_t size;
(*this) >> size;
assert(_s.size() >= (size * sizeof(Other)) + _pos);
vec.resize(size);
for (size_t i(0); i < size; i++)
(*this) >> vec[i];
return *this;
}
return *this;
}
void clear()
{
_s.clear();
_pos = 0;
}
void clear()
{
_s.clear();
_pos = 0;
}
private:
std::string _s;
std::size_t _pos;
};
} //serializer namespace
} //ana namespace
private:
std::string _s;
std::size_t _pos;
};
} //serializer namespace
#endif

296
src/ana/api/buffers.hpp Normal file
View file

@ -0,0 +1,296 @@
/* $Id$ */
/**
* @file buffers.hpp
* @brief Implementation details for the ana project dealing with buffers.
*
* ana: Asynchronous Network API.
* Copyright (C) 2010 Guillermo Biset.
*
* This file is part of the ana project.
*
* System: ana
* Language: C++
*
* Author: Guillermo Biset
* E-Mail: billybiset AT gmail DOT com
*
* ana is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ana is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ana. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANA_BUFFERS_HPP
#define ANA_BUFFERS_HPP
#ifndef ANA_DETAIL_INTERNAL_HPP
#error "Private file, do not include directly."
#endif
namespace ana
{
namespace detail
{
/**
* A simple buffer to read things on, supports conversion to string.
*/
class read_buffer_implementation
{
public:
/**
* Creates a new buffer in heap.
*
* @param size : The size of the buffer.
*/
read_buffer_implementation( size_t size ) :
base_( new char[ size ] ),
size_( size )
{
}
/** Deletes the buffer from heap. */
~read_buffer_implementation()
{
delete[] base_;
}
/**
* Get the base address.
*
* @returns A char* to the base address of the buffer.
*/
char* base_char() const
{
return base_;
}
/**
* Get the base address.
*
* @returns A void* to the base address of the buffer.
*/
void* base() const
{
return static_cast<void*>(base_);
}
/** Get the size of the buffer. */
size_t size() const
{
return size_;
}
/** Create a string from the buffer. */
std::string string()
{
return std::string( base_, size_ );
}
private:
char* base_;
size_t size_;
};
/** A shared pointer to a read_buffer, self destructs when no one is left referencing it. */
typedef boost::shared_ptr<read_buffer_implementation> read_buffer;
/**
* A buffer to be constructed from different buffers that can duplicate the other
* and hold a local copy that will destruct with the object itself.
*/
class copying_buffer
{
public:
copying_buffer( boost::asio::const_buffer buffer, ana::send_type copy_buffer) :
size_(boost::asio::detail::buffer_size_helper(buffer) ),
base_( NULL ),
copy_( copy_buffer )
{
if (copy_buffer)
{
base_ = std::malloc( size_ );
std::memcpy(base_, boost::asio::detail::buffer_cast_helper(buffer), size_);
}
else
base_ = const_cast<void*>(boost::asio::detail::buffer_cast_helper(buffer));
}
inline size_t size() const { return size_; }
inline void* base() const { return base_; }
~copying_buffer()
{
if (copy_)
std::free( base_ );
}
private:
const size_t size_;
void* base_;
const bool copy_;
};
/** A buffer that can be shared by many users. */
typedef boost::shared_ptr<detail::copying_buffer> shared_buffer;
} //namespace detail
/** @name Buffer creation methods
*
* @defgroup buffer
*
* API user should create buffers with one of these methods.
*
* Paraphrasing boost asio's documentation on the buffer function:
* The ana::buffer function is used to create a buffer object to represent raw memory,
* an array of POD elements, a vector of POD elements, or a std::string.
*
* Check <http://think-async.com/Asio/boost_asio_1_3_1/doc/html/boost_asio/reference/buffer.html>
*/
//@{
inline boost::asio::mutable_buffers_1 buffer(const boost::asio::mutable_buffer & b)
{
return boost::asio::buffer(b);
}
inline boost::asio::mutable_buffers_1 buffer(const boost::asio::mutable_buffer & b, std::size_t max_size_in_bytes)
{
return boost::asio::buffer(b, max_size_in_bytes);
}
inline boost::asio::const_buffers_1 buffer(const boost::asio::const_buffer & b)
{
return boost::asio::buffer(b);
}
inline boost::asio::const_buffers_1 buffer(const boost::asio::const_buffer & b, std::size_t max_size_in_bytes)
{
return boost::asio::buffer(b, max_size_in_bytes);
}
inline boost::asio::mutable_buffers_1 buffer(void * data, std::size_t size_in_bytes)
{
return boost::asio::buffer(data, size_in_bytes);
}
inline boost::asio::const_buffers_1 buffer(const void * data, std::size_t size_in_bytes)
{
return boost::asio::buffer(data, size_in_bytes);
}
template<typename PodType, std::size_t N>
inline boost::asio::mutable_buffers_1 buffer(PodType & data)
{
return boost::asio::buffer(data);
}
template<typename PodType, std::size_t N>
inline boost::asio::mutable_buffers_1 buffer(PodType & data, std::size_t max_size_in_bytes)
{
return boost::asio::buffer(data, max_size_in_bytes);
}
template<typename PodType, std::size_t N>
inline boost::asio::const_buffers_1 buffer(const PodType & data)
{
return boost::asio::buffer(data);
}
template<typename PodType, std::size_t N>
inline boost::asio::const_buffers_1 buffer(const PodType & data, std::size_t max_size_in_bytes)
{
return boost::asio::buffer(data, max_size_in_bytes);
}
template<typename PodType, std::size_t N>
inline boost::asio::mutable_buffers_1 buffer(boost::array< PodType, N > & data)
{
return boost::asio::buffer(data);
}
template<typename PodType, std::size_t N>
inline boost::asio::mutable_buffers_1 buffer(boost::array< PodType, N > & data,
std::size_t max_size_in_bytes)
{
return boost::asio::buffer(data, max_size_in_bytes);
}
template<typename PodType, std::size_t N>
inline boost::asio::const_buffers_1 buffer(boost::array< const PodType, N > & data)
{
return boost::asio::buffer(data);
}
template<typename PodType, std::size_t N>
inline boost::asio::const_buffers_1 buffer(boost::array< const PodType, N > & data,
std::size_t max_size_in_bytes)
{
return boost::asio::buffer(data, max_size_in_bytes);
}
template<typename PodType, std::size_t N>
inline boost::asio::const_buffers_1 buffer(const boost::array< PodType, N > & data)
{
return boost::asio::buffer(data);
}
template<typename PodType, std::size_t N>
inline boost::asio::const_buffers_1 buffer(const boost::array< PodType, N > & data,
std::size_t max_size_in_bytes)
{
return boost::asio::buffer(data, max_size_in_bytes);
}
template<typename PodType, typename Allocator>
inline boost::asio::mutable_buffers_1 buffer(std::vector< PodType, Allocator > & data)
{
return boost::asio::buffer(data);
}
template<typename PodType, typename Allocator>
inline boost::asio::mutable_buffers_1 buffer(std::vector< PodType, Allocator > & data,
std::size_t max_size_in_bytes)
{
return boost::asio::buffer(data, max_size_in_bytes);
}
template<typename PodType, typename Allocator>
inline boost::asio::const_buffers_1 buffer(const std::vector< PodType, Allocator > & data)
{
return boost::asio::buffer(data);
}
template<typename PodType, typename Allocator>
inline boost::asio::const_buffers_1 buffer(const std::vector< PodType, Allocator > & data,
std::size_t max_size_in_bytes)
{
return boost::asio::buffer(data, max_size_in_bytes);
}
inline boost::asio::const_buffers_1 buffer(const std::string & data)
{
return boost::asio::buffer(data);
}
inline boost::asio::const_buffers_1 buffer(const std::string & data, std::size_t max_size_in_bytes)
{
return boost::asio::buffer(data, max_size_in_bytes);
}
//@}
}
#endif

69
src/ana/api/common.hpp Normal file
View file

@ -0,0 +1,69 @@
/* $Id$ */
/**
* @file common.hpp
* @brief Main definitions for project ana.
*
* ana: Asynchronous Network API.
* Copyright (C) 2010 Guillermo Biset.
*
* This file is part of the ana project.
*
* System: ana
* Language: C++
*
* Author: Guillermo Biset
* E-Mail: billybiset AT gmail DOT com
*
* ana is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ana is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ana. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANA_COMMON_HPP
#define ANA_COMMON_HPP
#ifndef ANA_DETAIL_INTERNAL_HPP
#error "Private file, do not include directly."
#endif
namespace ana
{
/** @name Type and constant definitions
*
* Definitions of main types and relevant constants.
*/
//@{
typedef boost::uint32_t ana_uint32 /** Standard unsigned int, with fixed size to 32 bits. */ ;
typedef boost::int32_t ana_int32 /** Standard int, with fixed size to 32 bits. */ ;
typedef ana_uint32 client_id /** Type of IDs of connected components, unique. */ ;
typedef ana_uint32 message_size /** Message size type. */ ;
typedef std::string port /** Port type, a std::string (instead of a short.) */ ;
typedef std::string address /** Address type, a string. Either IP of hostname. */ ;
typedef bool send_type /** Send operation type, true to copy the buffer. */ ;
typedef boost::system::error_code error_code /** Standard error code, can evaluate to bool. */ ;
const send_type ZeroCopy = false /** Don't copy the buffer. */ ;
const send_type CopyBuffer = true /** Copy the buffer. */ ;
const message_size HeaderLength = sizeof(ana_uint32) /** Length of message header. */ ;
const client_id ServerID = 0 /** The ID of the server application. */ ;
}
#endif

View file

@ -1,247 +0,0 @@
/* $Id$ */
/**
* @file detail.hpp
* @brief Implementation details for the ana project. Private file, do not include directly.
*
* ana: Asynchronous Network API.
* Copyright (C) 2010 Guillermo Biset.
*
* This file is part of the ana project.
*
* System: ana
* Language: C++
*
* Author: Guillermo Biset
* E-Mail: billybiset AT gmail DOT com
*
* ana is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ana is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ana. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef DETAIL_INTERNAL_HPP
#error "Private file, do not include directly."
#endif
/** Used for implementation purposes. */
namespace detail
{
/**
* Intended for private use, should be created with create_predicate.
*
* \sa create_predicate
*/
template<class predicate>
class _generic_client_predicate : public client_predicate
{
public:
/** Construct via a generic object with overloaded operator(). */
_generic_client_predicate(const predicate& pred)
: pred(pred)
{
}
/** Copy constructor. */
_generic_client_predicate(const _generic_client_predicate<predicate>& other )
: pred(other.pred)
{
}
private:
const predicate pred /** The predicate object. */ ;
/**
* Implementation of the selection method using operator() from the
* predicate object.
*
* \sa client_predicate
*/
virtual bool selects(client_id cid) const
{
return pred(cid);
}
};
/**
* A simple buffer to read things on, supports conversion to string.
*/
class read_buffer_implementation
{
public:
/**
* Creates a new buffer in heap.
*
* @param size : The size of the buffer.
*/
read_buffer_implementation( size_t size ) :
base_( new char[ size ] ),
size_( size )
{
}
/** Deletes the buffer from heap. */
~read_buffer_implementation()
{
delete[] base_;
}
/**
* Get the base address.
*
* @returns A char* to the base address of the buffer.
*/
char* base_char() const
{
return base_;
}
/**
* Get the base address.
*
* @returns A void* to the base address of the buffer.
*/
void* base() const
{
return static_cast<void*>(base_);
}
/** Get the size of the buffer. */
size_t size() const
{
return size_;
}
/** Create a string from the buffer. */
std::string string()
{
return std::string( base_, size_ );
}
private:
char* base_;
size_t size_;
};
/** A shared pointer to a read_buffer, self destructs when no one is left referencing it. */
typedef boost::shared_ptr<read_buffer_implementation> read_buffer;
/**
* A buffer to be constructed from different buffers that can duplicate the other
* and hold a local copy that will destruct with the object itself.
*/
class copying_buffer
{
public:
copying_buffer( boost::asio::const_buffer buffer, ana::send_type copy_buffer) :
size_(boost::asio::detail::buffer_size_helper(buffer) ),
base_( NULL ),
copy_( copy_buffer )
{
if (copy_buffer)
{
base_ = std::malloc( size_ );
std::memcpy(base_, boost::asio::detail::buffer_cast_helper(buffer), size_);
}
else
base_ = const_cast<void*>(boost::asio::detail::buffer_cast_helper(buffer));
}
inline size_t size() const { return size_; }
inline void* base() const { return base_; }
~copying_buffer()
{
if (copy_)
std::free( base_ );
}
private:
const size_t size_;
void* base_;
const bool copy_;
};
/** A buffer that can be shared by many users. */
typedef boost::shared_ptr<detail::copying_buffer> shared_buffer;
/**
* A network sender component that can be configured to issue timeout events.
*/
class timed_sender
{
public:
/**
* Set the policy for timed operations (such as send.)
*
* @param type : Type of timeout policy.
* @param ms : Milliseconds related to the given policy, 0 means no timeouts.
*
* Examples:
* - set_timeouts( ana::NoTimeouts );
* - set_timeouts( ana::FixedTime, ana::time::minutes( 1 ) );
*
* \sa timeout_policy
* \sa ana::time
*/
void set_timeouts(timeout_policy type, size_t ms = 0)
{
timeout_milliseconds_ = ms;
if (ms > 0)
timeout_type_ = type;
else
timeout_type_ = NoTimeouts;
}
/**
* Start a timer given the current configuration.
*
* @param buffer : The buffer used in the send operation.
* @param handler : The handler of the timeout/abort event.
*
* @returns : A pointer to a newly created timer object.
*/
template<class Handler>
timer* start_timer( shared_buffer buffer, Handler handler ) const
{
if ( (timeout_milliseconds_ == 0) || (timeout_type_ == NoTimeouts) )
return NULL;
else
{
timer* t = new timer();
switch ( timeout_type_ ) //this should be more OO looking
{
case TimePerKilobyte :
t->wait( (buffer->size() / 1024.0) * timeout_milliseconds_, handler);
break;
default :
t->wait( timeout_milliseconds_, handler);
break;
}
return t;
}
}
protected:
/** Standard constructor. */
timed_sender() :
timeout_type_( NoTimeouts ),
timeout_milliseconds_( 0 )
{
}
timeout_policy timeout_type_ /** Type of timer policy. */ ;
size_t timeout_milliseconds_ /** Amount of ms relevant to this policy. */ ;
};
} //namespace details

116
src/ana/api/predicates.hpp Normal file
View file

@ -0,0 +1,116 @@
/* $Id$ */
/**
* @file predicates.hpp
* @brief Implementation details for the ana project dealing with client predicates.
*
* ana: Asynchronous Network API.
* Copyright (C) 2010 Guillermo Biset.
*
* This file is part of the ana project.
*
* System: ana
* Language: C++
*
* Author: Guillermo Biset
* E-Mail: billybiset AT gmail DOT com
*
* ana is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ana is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ana. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ANA_PREDICATES_HPP
#define ANA_PREDICATES_HPP
#ifndef ANA_DETAIL_INTERNAL_HPP
#error "Private file, do not include directly."
#endif
namespace ana
{
/** @name Predicates over client ids.
*
* Declaration of types used in conditional send operations, e.g. send_if.
* \sa send_if
*/
//@{
/** A boolean predicate of client IDs. Used for conditional send operations. */
struct client_predicate
{
/**
* Decides if a given condition applies to a client.
*
* @param client ID of the queried client.
* @returns true if the condition holds for this client.
*/
virtual bool selects(client_id) const = 0;
};
//@}
/**
* Intended for private use, should be created with create_predicate.
*
* \sa create_predicate
*/
template<class predicate>
class _generic_client_predicate : public client_predicate
{
public:
/** Construct via a generic object with overloaded operator(). */
_generic_client_predicate(const predicate& pred)
: pred(pred)
{
}
/** Copy constructor. */
_generic_client_predicate(const _generic_client_predicate<predicate>& other )
: pred(other.pred)
{
}
private:
const predicate pred /** The predicate object. */ ;
/**
* Implementation of the selection method using operator() from the
* predicate object.
*
* \sa client_predicate
*/
virtual bool selects(client_id cid) const
{
return pred(cid);
}
};
/**
* Creates a client predicate to be used in send operations.
*
* This function can be used to create predicate objects from the standard library's
* bind1st objects and from boost::bind too.
*
* Examples:
* - server_->send_if(boost::asio::buffer( str ), this, create_predicate(
* boost::bind( std::not_equal_to<client_id>(), client, _1) ) );
*
* @param pred Predicate of the queried client.
* @returns Predicate for client selection.
*/
template<class predicate>
_generic_client_predicate<predicate> create_predicate(const predicate& pred)
{
return _generic_client_predicate<predicate>(pred);
}
}
#endif

238
src/ana/api/timers.hpp Normal file
View file

@ -0,0 +1,238 @@
/* $Id$ */
/**
* @file timers.hpp
* @brief Implementation details for the ana project dealing with timers.
*
* ana: Asynchronous Network API.
* Copyright (C) 2010 Guillermo Biset.
*
* This file is part of the ana project.
*
* System: ana
* Language: C++
*
* Author: Guillermo Biset
* E-Mail: billybiset AT gmail DOT com
*
* ana is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ana is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ana. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "buffers.hpp"
#ifndef ANA_TIMERS_HPP
#define ANA_TIMERS_HPP
#ifndef ANA_DETAIL_INTERNAL_HPP
#error "Private file, do not include directly."
#endif
namespace ana
{
/**
* Timeout policies for send operations.
*
* \sa timer
*/
enum timeout_policy
{
NoTimeouts /** Don't use timers in any operation. */,
FixedTime /** Use timers with a fixed time for every operation. */,
TimePerKilobyte /** Use timers, calculating the necessary time from
the size of the buffer that is to be sent. */
};
/** @name Timers
*
* Definitions of timer related types.
*/
//@{
/**
* General purpose asynchronous timer.
*/
class timer
{
public:
/** Standard constructor. */
timer() :
io_service_(),
timer_(io_service_)
{
}
/**
* Wait in background a given amount of milliseconds.
*
* The method shouldn't be called with a size_t constant
* directly. Instead, the user should use the functions in
* the ana::time namespace.
*
* @param milliseconds : Amount of milliseconds to wait.
* @param handler : Handler object to handle the timeout event.
*
* Examples:
* - wait( ana::time::seconds(5),
* boost::bind( &ChatServer::handle_timeout, this,
* boost::asio::placeholders::error);
*
* \sa ana::time
*/
template<class Handler>
void wait(size_t milliseconds, Handler handler)
{
timer_.expires_from_now(milliseconds / 1000);
timer_.async_wait(handler);
boost::thread t( boost::bind( &boost::asio::io_service::run_one, &io_service_ ) );
}
/** Cancel the timer if running. */
void cancel()
{
timer_.cancel();
}
/** Standard destructor, cancels pending operations and stops the I/O service. */
~timer()
{
timer_.cancel();
io_service_.stop();
}
private:
/** Private class providing traits for the timer type. */
struct time_t_traits
{
// The time type.
typedef std::time_t time_type;
// The duration type.
struct duration_type
{
duration_type() : value(0) {}
duration_type(std::time_t v) : value(v) {}
std::time_t value;
};
// Get the current time.
static time_type now()
{
return std::time(0);
}
// Add a duration to a time.
static time_type add(const time_type& t, const duration_type& d)
{
return t + d.value;
}
// Subtract one time from another.
static duration_type subtract(const time_type& t1, const time_type& t2)
{
return duration_type(t1 - t2);
}
// Test whether one time is less than another.
static bool less_than(const time_type& t1, const time_type& t2)
{
return t1 < t2;
}
// Convert to POSIX duration type.
static boost::posix_time::time_duration to_posix_duration(const duration_type& d)
{
return boost::posix_time::seconds(d.value);
}
};
boost::asio::io_service io_service_;
boost::asio::basic_deadline_timer<std::time_t,time_t_traits> timer_;
};
namespace detail
{
/**
* A network sender component that can be configured to issue timeout events.
*/
class timed_sender
{
public:
/**
* Set the policy for timed operations (such as send.)
*
* @param type : Type of timeout policy.
* @param ms : Milliseconds related to the given policy, 0 means no timeouts.
*
* Examples:
* - set_timeouts( ana::NoTimeouts );
* - set_timeouts( ana::FixedTime, ana::time::minutes( 1 ) );
*
* \sa timeout_policy
* \sa ana::time
*/
void set_timeouts(timeout_policy type, size_t ms = 0)
{
timeout_milliseconds_ = ms;
if (ms > 0)
timeout_type_ = type;
else
timeout_type_ = NoTimeouts;
}
/**
* Start a timer given the current configuration.
*
* @param buffer : The buffer used in the send operation.
* @param handler : The handler of the timeout/abort event.
*
* @returns : A pointer to a newly created timer object.
*/
template<class Handler>
timer* start_timer( shared_buffer buffer, Handler handler ) const
{
if ( (timeout_milliseconds_ == 0) || (timeout_type_ == NoTimeouts) )
return NULL;
else
{
timer* t = new timer();
switch ( timeout_type_ ) //this should be more OO looking
{
case TimePerKilobyte :
t->wait( (buffer->size() / 1024.0) * timeout_milliseconds_, handler);
break;
default :
t->wait( timeout_milliseconds_, handler);
break;
}
return t;
}
}
protected:
/** Standard constructor. */
timed_sender() :
timeout_type_( NoTimeouts ),
timeout_milliseconds_( 0 )
{
}
timeout_policy timeout_type_ /** Type of timer policy. */ ;
size_t timeout_milliseconds_ /** Amount of ms relevant to this policy. */ ;
};
}
}
#endif

View file

@ -1,6 +1,6 @@
include_directories( ../api )
find_package( Boost 1.37 REQUIRED COMPONENTS thread system)
find_package( Boost 1.35 REQUIRED COMPONENTS thread system)
set ( server_srcs asio_server.cpp asio_listener.cpp )

View file

@ -124,7 +124,7 @@ void asio_client::connect( ana::connection_handler* handler )
}
catch (const std::exception& e)
{
handler->handle_connect( boost::system::error_code(1,boost::system::get_generic_category() ), 0 );
handler->handle_connect( boost::system::error_code(1,boost::system::system_category ), 0 );
std::cerr << "Client: An error ocurred, " << e.what() << std::endl;
}
}

View file

@ -126,6 +126,6 @@ void asio_listener::listen_one_message()
}
catch(const std::exception& e)
{
disconnect(listener_, boost::system::error_code(1,boost::system::get_generic_category() ));
disconnect(listener_, boost::system::error_code(1,boost::system::system_category) );
}
}

View file

@ -146,13 +146,13 @@ void proxy_connection::handle_response(boost::asio::streambuf* buf,
}
else //TODO: digest authentication support here
manager_->handle_proxy_connection(
boost::system::error_code(1,boost::system::get_generic_category() ),
boost::system::error_code(1,boost::system::system_category ),
conn_handler_);
}
else //Couldn't connect, wrong password or wasn't offered the possibility to authenticate
manager_->handle_proxy_connection(
boost::system::error_code(1,boost::system::get_generic_category() ),
boost::system::error_code(1,boost::system::system_category ),
conn_handler_);
}
}
@ -222,7 +222,7 @@ void proxy_connection::do_connect()
catch (const std::exception& e)
{
manager_->handle_proxy_connection(
boost::system::error_code(1,boost::system::get_generic_category() ),
boost::system::error_code(1,boost::system::system_category),
conn_handler_ );
}
}