network_manager_ana.hpp

Go to the documentation of this file.
00001 /* $Id: network_manager_ana.hpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 
00003 /**
00004  * @file
00005  * @brief Header file for network features using ana.
00006  *
00007  * Copyright (C) 2010 - 2012 Guillermo Biset.
00008  *
00009  * Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014    (at your option) any later version.
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY.
00017  *
00018  * See the COPYING file for more details.
00019  */
00020 
00021 #include <set>
00022 #include <queue>
00023 
00024 #include <boost/thread.hpp>
00025 #include <boost/variant.hpp>
00026 
00027 #include "network.hpp"
00028 #include "ana/api/ana.hpp"
00029 
00030 #ifndef NETWORK_MANAGER_ANA_HPP_INCLUDED
00031 #define NETWORK_MANAGER_ANA_HPP_INCLUDED
00032 
00033 /**
00034  * A representative of a network component to the application.
00035  */
00036 class ana_component
00037 {
00038     public:
00039         /** Constructs a server component. */
00040         ana_component( );
00041 
00042         ~ana_component( );
00043 
00044         /**
00045          * Constructs a client component.
00046          *
00047          * @param host : The hostname to which it is supposed to connect to.
00048          * @param port : The port it is supposed to connect to.
00049          */
00050         ana_component( const std::string& host, const std::string& port);
00051 
00052         /** Get network upload statistics for this component. */
00053         network::statistics get_send_stats() const;
00054 
00055         /** Get network download statistics for this component. */
00056         network::statistics get_receive_stats() const;
00057 
00058         /**
00059          * Get the pointer to an ana::server object for this component.
00060          *
00061          * @pre : This component is a server.
00062          */
00063         ana::server* server() const;
00064 
00065         /**
00066          * Get the pointer to an ana::client object for this component.
00067          *
00068          * @pre : This component is a client.
00069          */
00070         ana::client* client() const;
00071 
00072         /**
00073          * Get the pointer to an ana::listener object for this component.
00074          * Both an ana::client an the ana::server are listeners.
00075          */
00076         ana::detail::listener* listener() const;
00077 
00078         /** Returns true iff this component is a server. */
00079         bool is_server() const;
00080 
00081         /** Returns true iff this component is a client. */
00082         bool is_client() const;
00083 
00084         /** Returns this component's id. */
00085         ana::net_id get_id() const;
00086 
00087         network::connection get_wesnoth_id() const;
00088 
00089         void set_wesnoth_id( network::connection ) ;
00090 
00091         /** Returns a pointer to the ana::stats object for accumulated network stats. */
00092         const ana::stats* get_stats( ana::stat_type type = ana::ACCUMULATED ) const;
00093 
00094         /** Push a buffer to the queue of incoming messages. */
00095         void add_buffer(ana::read_buffer buffer, ana::net_id id);
00096 
00097         /**
00098          * Blocking operation to wait for a message in a component.
00099          *
00100          * @returns The buffer that was received first from all pending buffers.
00101          */
00102         ana::read_buffer wait_for_element();
00103 
00104         /** Returns the network id of the oldest sender of a pending buffer. */
00105         network::connection oldest_sender_id_still_pending();
00106 
00107         /** Returns true iff. the component has a read buffer ready that hasn't been returned. */
00108         bool new_buffer_ready(); // non const due to mutex blockage
00109 
00110     private:
00111         boost::variant<ana::server*, ana::client*> base_;
00112 
00113         bool        is_server_;
00114 
00115         ana::net_id         id_;
00116         network::connection wesnoth_id_;
00117 
00118         //Buffer queue attributes
00119         boost::mutex                   mutex_;
00120         boost::condition_variable      condition_;
00121 
00122         std::queue< ana::read_buffer > buffers_;
00123         std::queue< network::connection >      sender_ids_;
00124 };
00125 
00126 typedef std::set<ana_component*> ana_component_set;
00127 
00128 /**
00129  * Manages connected client ids for a given server.
00130  */
00131 class clients_manager : public ana::connection_handler
00132 {
00133     public:
00134         /** Constructor. */
00135         clients_manager( ana::server* );
00136 
00137         /** Returns the amount of components connected to this server. */
00138         size_t client_amount() const;
00139 
00140         void connected( ana::net_id id );
00141 
00142         void remove( ana::net_id id );
00143 
00144         void handshaked( ana::net_id id );
00145 
00146         bool has_connection_pending() const;
00147 
00148         bool is_pending_handshake( ana::net_id ) const;
00149 
00150         bool is_a_client( ana::net_id id ) const;
00151 
00152         network::connection get_pending_connection_id();
00153 
00154     private:
00155         virtual void handle_connect(ana::error_code error, ana::net_id client);
00156 
00157         virtual void handle_disconnect(ana::error_code /*error*/, ana::net_id client);
00158 
00159         ana::server*                    server_; // the server managing these clients
00160 
00161         std::set< ana::net_id >         ids_;
00162         std::set< network::connection > pending_ids_;
00163         std::set< ana::net_id >         pending_handshakes_;
00164 };
00165 
00166 /**
00167  * To use the asynchronous library synchronously, objects of this
00168  * type lock a mutex until enough calls have been made to the
00169  * associated handler.
00170  */
00171 class ana_send_handler : public ana::send_handler
00172 {
00173     public:
00174         /**
00175          * Constructs a handler object.
00176          * @param calls [optional, default 1] : The amount of calls to the handler expected.
00177          */
00178         ana_send_handler( size_t calls = 1 );
00179 
00180         /** Destructor, checks that the necessary calls were made. */
00181         ~ana_send_handler();
00182 
00183         /** Locks current thread until all the calls are made. */
00184         void wait_completion();
00185 
00186         const ana::error_code& error() const
00187         {
00188             return error_code_;
00189         }
00190 
00191     private:
00192         virtual void handle_send(ana::error_code, ana::net_id, ana::operation_id);
00193 
00194         boost::mutex       mutex_;
00195         size_t             target_calls_;
00196         ana::error_code    error_code_;
00197 };
00198 
00199 class ana_handshake_finisher_handler : public ana::send_handler
00200 {
00201     public:
00202         ana_handshake_finisher_handler( ana::server*, clients_manager* );
00203 
00204         ~ana_handshake_finisher_handler();
00205     private:
00206 
00207         virtual void handle_send(ana::error_code, ana::net_id, ana::operation_id);
00208 
00209         ana::server*       server_;
00210         clients_manager*   manager_;
00211 };
00212 
00213 
00214 /**
00215  * To use the asynchronous library synchronously, objects of this
00216  * type lock a mutex until enough calls have been made to the
00217  * associated handler.
00218  */
00219 class ana_receive_handler : public ana::listener_handler
00220 {
00221     public:
00222         /**
00223          * Constructs a reader handler object.
00224          */
00225         ana_receive_handler( ana_component_set::iterator );
00226 
00227         /** Destructor. */
00228         ~ana_receive_handler();
00229 
00230         /**
00231          * Attempts to read from those network components associated with this
00232          * handler object up until timeout_ms milliseconds.
00233          *
00234          * If the timeout parameter is 0, it will lock the current thread until
00235          * one of these components has received a message.
00236          *
00237          * @param component : A network component running an io_service which
00238          *                    supports timeout capabilities.
00239          * @param timeout_ms : Amount of milliseconds to timeout the operation.
00240          */
00241         void wait_completion(ana::detail::timed_sender* component, size_t timeout_ms = 0);
00242 
00243         /** Returns the error_code from the operation. */
00244         const ana::error_code& error() const
00245         {
00246             return error_code_;
00247         }
00248 
00249     private:
00250         virtual void handle_receive   (ana::error_code, ana::net_id, ana::read_buffer);
00251         virtual void handle_disconnect(ana::error_code, ana::net_id);
00252 
00253         void handle_timeout(ana::error_code error_code);
00254 
00255         ana_component_set::iterator iterator_;
00256 
00257         boost::mutex             mutex_;
00258         boost::mutex             handler_mutex_;
00259         boost::mutex             timeout_called_mutex_;
00260         ana::error_code          error_code_;
00261         ana::timer*              receive_timer_;
00262         bool                     finished_;
00263 };
00264 
00265 /**
00266  * To use the asynchronous library synchronously, objects of this
00267  * type lock a mutex until enough calls have been made to the
00268  * associated handler.
00269  */
00270 class ana_multiple_receive_handler : public ana::listener_handler
00271 {
00272     public:
00273         /**
00274          * Constructs a reader handler object.
00275          */
00276         ana_multiple_receive_handler( ana_component_set& components );
00277 
00278         /** Destructor. */
00279         ~ana_multiple_receive_handler();
00280 
00281         /**
00282          * Attempts to read from those network components associated with this
00283          * handler object up until timeout_ms milliseconds.
00284          *
00285          * If the timeout parameter is 0, it will lock the current thread until
00286          * one of these components has received a message.
00287          *
00288          * @param component : A network component running an io_service
00289          *                    which supports timeout capabilities.
00290          * @param timeout_ms : Amount of milliseconds to timeout the operation.
00291          */
00292         void wait_completion(size_t timeout_ms = 0);
00293 
00294         /** Returns the error_code from the operation. */
00295         const ana::error_code& error() const
00296         {
00297             return error_code_;
00298         }
00299 
00300         /** Returns the buffer from the operation. */
00301         ana::read_buffer buffer() const
00302         {
00303             return buffer_;
00304         }
00305 
00306         network::connection get_wesnoth_id() const
00307         {
00308             return wesnoth_id_;
00309         }
00310 
00311     private:
00312         virtual void handle_receive   (ana::error_code, ana::net_id, ana::read_buffer);
00313         virtual void handle_disconnect(ana::error_code, ana::net_id);
00314 
00315         void handle_timeout(ana::error_code error_code);
00316 
00317         ana_component_set& components_;
00318 
00319         boost::mutex             mutex_;
00320         boost::mutex             handler_mutex_;
00321         boost::mutex             timeout_called_mutex_;
00322         ana::error_code          error_code_;
00323         ana::read_buffer buffer_;
00324         network::connection      wesnoth_id_;
00325         ana::timer*              receive_timer_;
00326         bool                     finished_;
00327 };
00328 
00329 
00330 
00331 /**
00332  * To use the asynchronous library synchronously, objects of this
00333  * type lock a mutex until enough calls have been made to the
00334  * associated handler.
00335  */
00336 class ana_connect_handler : public ana::connection_handler
00337 {
00338     public:
00339         /**
00340          * Constructs a connection handler.
00341          *
00342          * @param timer : A pointer to a running timer dealing with the timeout
00343          *                of this connect operation.
00344          */
00345         ana_connect_handler( );
00346 
00347         /** Destructor. */
00348         ~ana_connect_handler();
00349 
00350         /**
00351          * Checks if an error occurred during the connection procedure.
00352          *
00353          * @returns Error code of the operation.
00354          */
00355         const ana::error_code& error() const;
00356 
00357         /** Locks current thread until the connection attempt has finished. */
00358         void wait_completion();
00359 
00360     private:
00361         virtual void handle_connect(ana::error_code error_code, ana::net_id /*client*/);
00362 
00363         boost::mutex       mutex_;
00364         ana::error_code    error_code_;
00365 };
00366 
00367 /**
00368  * Provides network functionality for Wesnoth using the ana API and library.
00369  */
00370 class ana_network_manager : public ana::listener_handler,
00371                             public ana::send_handler
00372 {
00373     public:
00374         /** Constructor. */
00375         ana_network_manager();
00376 
00377         /**
00378          * Create a server component and return it's ID.
00379          *
00380          * @returns The ID of the new created server.
00381          */
00382         ana::net_id create_server( );
00383 
00384         /**
00385          * Create a client component and return it's network connection number.
00386          *
00387          * @returns The ID of the new created client, as a network::connection number.
00388          */
00389         network::connection create_client_and_connect(std::string host, int port);
00390 
00391         network::connection new_connection_id( );
00392 
00393         /**
00394          * Get the associated stats of a given component.
00395          *
00396          * @param connection_num : The ID of the network component.
00397          *
00398          * @returns A pointer to an ana::stats object of the given component.
00399          */
00400         const ana::stats* get_stats( network::connection connection_num = 0,
00401                                      ana::stat_type type = ana::ACCUMULATED);
00402 
00403         /** Close all connections and clean up memory. */
00404         void close_connections_and_cleanup();
00405 
00406         /** Throw a Client Disconnected network::error if a disconnection hasn't been informed. */
00407         void throw_if_pending_disconnection();
00408 
00409         /**
00410          * Start a server on a given port.
00411          *
00412          * @param id : The ID of the server component.
00413          * @param port : The port on which to listen for new connections.
00414          */
00415         void run_server(ana::net_id id, int port);
00416 
00417         /** Get the IP address of a connected component by it's ID. */
00418         std::string ip_address( network::connection id );
00419 
00420         /** The amount of connected components to every server object created. */
00421         size_t number_of_connections() const;
00422 
00423         /** Send data to all created components. */
00424         size_t send_all( const config& cfg );
00425 
00426         /** Send data to the component with a given ID. */
00427         size_t send( network::connection connection_num , const config& cfg );
00428 
00429         size_t send_raw_data( const char*, size_t, network::connection);
00430 
00431         void send_all_except(const config& cfg, network::connection connection_num);
00432 
00433         /**
00434          * Read a message from a given component or from every one.
00435          *
00436          * @param connection_num : The id of the network component, 0 to read from every component.
00437          * @param cfg : The config input to place the read data.
00438          * @param timeout_ms : Amount of milliseconds to wait for the data.
00439          *
00440          * @returns The network::connection number of the component that read
00441          *          the data or 0 if an error occurred.
00442          */
00443         network::connection read_from( network::connection connection_num,
00444                                        config&             cfg,
00445                                        size_t              timeout_ms = 0 );
00446 
00447         /**
00448          * Read a message from a given component or from every one.
00449          *
00450          * @param it : The ana component to read from.
00451          * @param cfg : The config input to place the read data.
00452          * @param timeout_ms : Amount of milliseconds to wait for the data.
00453          *
00454          * @returns The network::connection number of the component that read
00455          *          the data or 0 if an error occurred.
00456          */
00457         network::connection read_from( const ana_component_set::iterator& it,
00458                                        config&             cfg,
00459                                        size_t              timeout_ms = 0 );
00460 
00461         network::connection read_from_all( std::vector<char>& );
00462 
00463         /**
00464          * Read a message from a given component or from every one.
00465          *
00466          * @param it : The ana component to read from.
00467          * @param cfg : The config input to place the read data.
00468          *
00469          * @returns The network::connection number of the component that read
00470          *          the data or 0 if an error occurred.
00471          */
00472         network::connection read_from_ready_buffer( const ana_component_set::iterator& it,
00473                                                     config&                            cfg);
00474 
00475         /** Retrieve upload statistics on a given component. */
00476         network::statistics get_send_stats(network::connection handle);
00477 
00478         /** Retrieve download statistics on a given component. */
00479         network::statistics get_receive_stats(network::connection handle);
00480 
00481         /**
00482          * Disconnect a given client.
00483          *
00484          * @param handle : The ID of the component (should be a client) to be disconnected.
00485          */
00486         bool disconnect( network::connection handle);
00487 
00488         //@{
00489         /**
00490          * Attempt to connect through a proxy (as opposed to directly.)
00491          *
00492          * Use the set_proxy_* methods to configure the connection options.
00493          */
00494         void enable_connection_through_proxy();
00495 
00496         /**
00497          * Set the address of the proxy. Default: "localhost".
00498          *
00499          * @param address: Network address where the proxy server should be running.
00500          */
00501         void set_proxy_address ( const std::string& address  );
00502 
00503         /**
00504          * Set the port of the proxy. Default: "3128".
00505          *
00506          * @param port: Network port where the proxy server should be listening.
00507          */
00508         void set_proxy_port    ( const std::string& port     );
00509 
00510         /**
00511          * Set the user to authenticate with the proxy. Default: "".
00512          *
00513          * @param user: User name to use for authentication purposes.
00514          */
00515         void set_proxy_user    ( const std::string& user     );
00516 
00517         /**
00518          * Set the password to authenticate with the proxy. Default: "".
00519          *
00520          * @param password: Password to use for authentication purposes.
00521          */
00522         void set_proxy_password( const std::string& password );
00523         //@}
00524     private:
00525         virtual void handle_send(ana::error_code, ana::net_id, ana::operation_id);
00526 
00527         virtual void handle_receive( ana::error_code          error,
00528                                      ana::net_id              client,
00529                                      ana::read_buffer buffer);
00530 
00531         virtual void handle_disconnect(ana::error_code /*error_code*/, ana::net_id client);
00532 
00533         struct proxy_settings
00534         {
00535             proxy_settings() :
00536                 enabled(false),
00537                 address(),
00538                 port(),
00539                 user(),
00540                 password()
00541             {
00542             }
00543 
00544             bool        enabled;
00545             std::string address;
00546             std::string port;
00547             std::string user;
00548             std::string password;
00549         };
00550 
00551         /**
00552          * Pack a config object to an outpt stream using compression.
00553          *
00554          * @param cfg : The config object as input.
00555          * @param out : The output stream as output.
00556          */
00557         void compress_config( const config& cfg, std::ostringstream& out);
00558 
00559         std::string compress_config( const config& cfg);
00560 
00561         /**
00562          * Read a config object from an input buffer.
00563          *
00564          * @param buffer : The buffer with the compressed stream as input.
00565          * @param cfg : The config object as output.
00566          */
00567         void read_config( const ana::read_buffer& buffer, config& cfg);
00568 
00569         // Attributes
00570         ana::timer*                connect_timer_;
00571         ana_component_set          components_;
00572 
00573         std::map< ana::server*, clients_manager* > server_manager_;
00574 
00575         /** Clients that have disconnected from servers (used for client applications.) */
00576         std::queue< ana_component* > disconnected_components_;
00577 
00578         /** Client IDs that have disconnected from a serve (used in servers applications.) */
00579         std::queue< ana::net_id >    disconnected_ids_;
00580 
00581         proxy_settings               proxy_settings_;
00582 };
00583 
00584 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:07 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs