From 83f105b6b3cab1d8ffa499f84cb556ada380c389 Mon Sep 17 00:00:00 2001 From: Guillermo Biset Date: Thu, 10 Jun 2010 23:18:14 +0000 Subject: [PATCH] Separated ana.hpp & detail.hpp into several single-purpose files... ...and updated error_code creation to comply with boost 1.35. --- src/ana/api/ana.hpp | 422 +++----------------------- src/ana/api/binary_streams.hpp | 204 +++++++------ src/ana/api/buffers.hpp | 296 ++++++++++++++++++ src/ana/api/common.hpp | 69 +++++ src/ana/api/detail.hpp | 247 --------------- src/ana/api/predicates.hpp | 116 +++++++ src/ana/api/timers.hpp | 238 +++++++++++++++ src/ana/src/CMakeLists.txt | 2 +- src/ana/src/asio_client.cpp | 2 +- src/ana/src/asio_listener.cpp | 2 +- src/ana/src/asio_proxy_connection.cpp | 6 +- 11 files changed, 876 insertions(+), 728 deletions(-) create mode 100644 src/ana/api/buffers.hpp create mode 100644 src/ana/api/common.hpp delete mode 100644 src/ana/api/detail.hpp create mode 100644 src/ana/api/predicates.hpp create mode 100644 src/ana/api/timers.hpp diff --git a/src/ana/api/ana.hpp b/src/ana/api/ana.hpp index 6efcbeff30e..642bc8adcea 100644 --- a/src/ana/api/ana.hpp +++ b/src/ana/api/ana.hpp @@ -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 #include #include @@ -68,184 +65,22 @@ #include #include +#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 - 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 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, _1) ) ); - * - * @param pred Predicate of the queried client. - * @returns Predicate for client selection. - */ - template - detail::_generic_client_predicate create_predicate(const predicate& pred) - { - return detail::_generic_client_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 - */ - //@{ - - 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 - inline boost::asio::mutable_buffers_1 buffer(PodType & data) - { - return boost::asio::buffer(data); - } - - template - 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 - inline boost::asio::const_buffers_1 buffer(const PodType & data) - { - return boost::asio::buffer(data); - } - - template - 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 - inline boost::asio::mutable_buffers_1 buffer(boost::array< PodType, N > & data) - { - return boost::asio::buffer(data); - } - - template - 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 - inline boost::asio::const_buffers_1 buffer(boost::array< const PodType, N > & data) - { - return boost::asio::buffer(data); - } - - template - 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 - inline boost::asio::const_buffers_1 buffer(const boost::array< PodType, N > & data) - { - return boost::asio::buffer(data); - } - - template - 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 - inline boost::asio::mutable_buffers_1 buffer(std::vector< PodType, Allocator > & data) - { - return boost::asio::buffer(data); - } - - template - 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 - inline boost::asio::const_buffers_1 buffer(const std::vector< PodType, Allocator > & data) - { - return boost::asio::buffer(data); - } - - template - 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 diff --git a/src/ana/api/binary_streams.hpp b/src/ana/api/binary_streams.hpp index f348eb8d46a..acff02aa1fd 100644 --- a/src/ana/api/binary_streams.hpp +++ b/src/ana/api/binary_streams.hpp @@ -40,123 +40,127 @@ #include #include -namespace serializer +namespace ana { - class bostream + namespace serializer { - public: - bostream() : - _s() - { - } + class bostream + { + public: + bostream() : + _s() + { + } - template - bostream& operator<< (T x) - { - _s.append(reinterpret_cast(&x), sizeof(T)); - return *this; - } + template + bostream& operator<< (T x) + { + _s.append(reinterpret_cast(&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 - bostream& operator<< (const std::vector& vec) - { - const uint32_t size(vec.size()); - (*this) << size; - for (size_t i(0); i < size; ++i) - (*this) << vec[i]; + template + bostream& operator<< (const std::vector& 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 - bistream& operator >> (T& x) - { - assert(_s.size() >= _pos + sizeof(x)); - _pos += _s.copy(reinterpret_cast(&x), sizeof(x),_pos); - return *this; - } + template + bistream& operator >> (T& x) + { + assert(_s.size() >= _pos + sizeof(x)); + _pos += _s.copy(reinterpret_cast(&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 - bistream& operator>> (std::vector& 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 + bistream& operator>> (std::vector& 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 diff --git a/src/ana/api/buffers.hpp b/src/ana/api/buffers.hpp new file mode 100644 index 00000000000..b4e68dc8d5a --- /dev/null +++ b/src/ana/api/buffers.hpp @@ -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 . +* +*/ + +#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(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; + + + /** + * 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(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 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 + */ + //@{ + + 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 + inline boost::asio::mutable_buffers_1 buffer(PodType & data) + { + return boost::asio::buffer(data); + } + + template + 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 + inline boost::asio::const_buffers_1 buffer(const PodType & data) + { + return boost::asio::buffer(data); + } + + template + 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 + inline boost::asio::mutable_buffers_1 buffer(boost::array< PodType, N > & data) + { + return boost::asio::buffer(data); + } + + template + 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 + inline boost::asio::const_buffers_1 buffer(boost::array< const PodType, N > & data) + { + return boost::asio::buffer(data); + } + + template + 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 + inline boost::asio::const_buffers_1 buffer(const boost::array< PodType, N > & data) + { + return boost::asio::buffer(data); + } + + template + 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 + inline boost::asio::mutable_buffers_1 buffer(std::vector< PodType, Allocator > & data) + { + return boost::asio::buffer(data); + } + + template + 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 + inline boost::asio::const_buffers_1 buffer(const std::vector< PodType, Allocator > & data) + { + return boost::asio::buffer(data); + } + + template + 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 \ No newline at end of file diff --git a/src/ana/api/common.hpp b/src/ana/api/common.hpp new file mode 100644 index 00000000000..aeb7c4abaad --- /dev/null +++ b/src/ana/api/common.hpp @@ -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 . +* +*/ + +#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 \ No newline at end of file diff --git a/src/ana/api/detail.hpp b/src/ana/api/detail.hpp deleted file mode 100644 index 52f18baa40f..00000000000 --- a/src/ana/api/detail.hpp +++ /dev/null @@ -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 . - * - */ - -#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 _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& 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(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; - - /** - * 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(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 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 - 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 diff --git a/src/ana/api/predicates.hpp b/src/ana/api/predicates.hpp new file mode 100644 index 00000000000..7361e138ea8 --- /dev/null +++ b/src/ana/api/predicates.hpp @@ -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 . + * + */ + +#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 _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& 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, _1) ) ); + * + * @param pred Predicate of the queried client. + * @returns Predicate for client selection. + */ + template + _generic_client_predicate create_predicate(const predicate& pred) + { + return _generic_client_predicate(pred); + } +} + +#endif \ No newline at end of file diff --git a/src/ana/api/timers.hpp b/src/ana/api/timers.hpp new file mode 100644 index 00000000000..b8c929776cf --- /dev/null +++ b/src/ana/api/timers.hpp @@ -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 . + * + */ + +#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 + 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 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 + 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 \ No newline at end of file diff --git a/src/ana/src/CMakeLists.txt b/src/ana/src/CMakeLists.txt index d97f6e55089..3c6e30b497f 100644 --- a/src/ana/src/CMakeLists.txt +++ b/src/ana/src/CMakeLists.txt @@ -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 ) diff --git a/src/ana/src/asio_client.cpp b/src/ana/src/asio_client.cpp index a0801d35f3e..610c5c2ed47 100644 --- a/src/ana/src/asio_client.cpp +++ b/src/ana/src/asio_client.cpp @@ -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; } } diff --git a/src/ana/src/asio_listener.cpp b/src/ana/src/asio_listener.cpp index ce5568b5fea..3de51f8cf7e 100644 --- a/src/ana/src/asio_listener.cpp +++ b/src/ana/src/asio_listener.cpp @@ -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) ); } } \ No newline at end of file diff --git a/src/ana/src/asio_proxy_connection.cpp b/src/ana/src/asio_proxy_connection.cpp index ddbf07443ba..096a10264c8 100644 --- a/src/ana/src/asio_proxy_connection.cpp +++ b/src/ana/src/asio_proxy_connection.cpp @@ -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_ ); } }