MACE  1.0.0
 All Classes Namespaces Files Functions Variables Enumerations Defines
libs/rpc/include/mace/rpc/detail/connection_base.hpp
00001 #ifndef _MACE_RPC_DETAIL_CONNECTION_BASE_HPP_
00002 #define _MACE_RPC_DETAIL_CONNECTION_BASE_HPP_
00003 #include <mace/rpc/connection_base.hpp>
00004 #include <boost/unordered_map.hpp>
00005 #include <boost/lexical_cast.hpp>
00006 
00007 namespace mace { namespace rpc { namespace detail {
00008   typedef boost::unordered_map<std::string,method> method_map;
00009   typedef std::map<int32_t,pending_result::ptr>    pending_map;
00010 
00016   class connection_base {
00017     public:
00018       typedef boost::shared_ptr<connection_base> ptr;
00019       method_map  methods;
00020       pending_map results;
00021       int32_t     next_method_id;
00022       int32_t     next_req_id;
00023 
00024       connection_base():next_method_id(0),next_req_id(0){}
00025       virtual ~connection_base(){}
00026 
00027       virtual void close() {}
00028       virtual void send( message&& m ) = 0;
00029       virtual void handle_error( message::error_type, const std::string& message ) = 0;
00030 
00031       void break_promises() {
00032         auto itr = results.begin();
00033         while( itr != results.end() ) {
00034           itr->second->handle_error( message::broken_promise, datavec() );
00035           ++itr;
00036         }
00037         results.clear();
00038       }
00039 
00044       void handle( message&& m ) {
00045         if( m.meth.size() ) {
00046           auto itr = methods.find( m.meth );
00047           if( itr != methods.end() ) {
00048              send( itr->second( m ) );
00049           } else {
00050              handle_error( message::unknown_method, m.meth ); 
00051           }
00052         } else if( m.id ) {
00053           auto itr = results.find( *m.id );
00054           if( itr != results.end() ) {
00055             if( !m.err ) {
00056               itr->second->handle_value( std::move( m.data ) );
00057             } else {
00058               itr->second->handle_error( m.err, std::move(m.data) );
00059             }
00060             results.erase(itr);
00061           } else {
00062              handle_error( message::invalid_response, "Unexpected response id "+ boost::lexical_cast<std::string>(*m.id)  ); 
00063           }
00064         } else {
00065           handle_error( message::invalid_response, "no method or request id" );
00066         }
00067       }
00068   };
00069   
00070 } } }
00071 
00072 #endif // _MACE_RPC_DETAIL_CONNECTION_BASE_HPP_