//////////////////////////////////////////////////////////////////////////////////////////////// // transport.h // $Header: xxx/transport.h,v 1.7 2005/04/14 13:30:35 my Exp $ // // Copyright (C) 2005 xxx.ru // #ifndef TRANSPORT_H #define TRANSPORT_H #include #include #include "textrpc.h" //////////////////////////////////////////////////////////////////////////////////////////////// namespace textrpc { //////////////////////////////////////////////////////////////////////////////////////////////// typedef std::auto_ptr request_ptr; typedef std::auto_ptr response_ptr; //////////////////////////////////////////////////////////////////////////////////////////////// // There are three simple abstractions: link, endpoint and linker. Link handles // sending messages, endpoint handles received messages and uses link for // sending messages, linker creates and owns links and passes them to the // associated endpoint. /* int server_main() { server srv; acceptor ac; ac.link("10.0.0.1:5000", srv); dispatch_event_loop(); } int client_main() { client cli; connector cn; cn.link("10.0.0.1:5000", cli); dispatch_event_loop(); } */ //////////////////////////////////////////////////////////////////////////////////////////////// // Link represents a link (connected or connectionless) to another party. It's // unidirectional, which means it's only used for sending either requests // (client link) or responses (server link). Received messages go directly to // enpoint::handle() along with the link. Links are created by linker and passed // to endpoint. template struct link { typedef Outbound outbound_type; typedef int id_type; virtual ~link() {} virtual id_type id() const = 0; virtual void send(outbound_type const&) = 0; virtual void unlink() = 0; }; typedef link client_link; typedef link server_link; //////////////////////////////////////////////////////////////////////////////////////////////// // We deal with unidirectional communications only. This distinction makes // things easier to think of and implement. Thus, an endpoint is either a client // sending requests and receiving responses, or a server receiving requests and // sending responses. template struct endpoint { typedef Outbound outbound_type; typedef Inbound inbound_type; typedef std::auto_ptr inbound_ptr; typedef link link_type; typedef typename link_type::id_type id_type; virtual ~endpoint() {} // Bellow are the flesh and bones of endpoint where all work is done. // called by linker when link establishment fails virtual void link_failed(id_type) = 0; // called when a connection has been established by linker with zero // inbound_ptr and when there is a message received from the other party virtual void handle(link_type&, inbound_ptr) = 0; // called when connection was torn down enum unlink_reason { eof = 0, soft_error = eof, error, timeout_read, timeout_write }; virtual void unlink(link_type&, unlink_reason) = 0; }; typedef endpoint client; typedef endpoint server; typedef std::auto_ptr server_ptr; typedef std::auto_ptr client_ptr; //////////////////////////////////////////////////////////////////////////////////////////////// // Linker abstracts out connection establishment. In async communications there // seems to be little difference between connect() and accept(), since results // of both calls are delivered asynchronously as callbacks to enpoint::handle(). template struct linker { typedef Endpoint endpoint_type; typedef typename Endpoint::link_type link_type; typedef typename link_type::id_type id_type; typedef std::string address_type; virtual ~linker() {} virtual id_type link(address_type const&, endpoint_type&) = 0; virtual void unlink(id_type) = 0; }; typedef linker listener; typedef linker connector; typedef std::auto_ptr listener_ptr; typedef std::auto_ptr connector_ptr; //////////////////////////////////////////////////////////////////////////////////////////////// namespace detail { //////////////////////////////////////////////////////////////////////////////////////////////// template struct link_type; template struct endpoint_type; template struct linker_type; template struct link_type > { typedef link type; }; template struct link_type > { typedef link type; }; template struct link_type > : link_type {}; template<> struct endpoint_type > { typedef client type; }; template<> struct endpoint_type > { typedef server type; }; template struct endpoint_type > { typedef endpoint type; }; template struct endpoint_type > { typedef T type; }; template struct linker_type > { typedef linker >::type> type; }; template struct linker_type > { typedef linker > type; }; template struct linker_type > { typedef linker type; }; //////////////////////////////////////////////////////////////////////////////////////////////// template struct tagged_endpoint : Endpoint { typedef Tag tag_type; typedef typename Endpoint::inbound_ptr inbound_ptr; typedef typename Endpoint::outbound_type outbound_type; typedef typename Endpoint::link_type link_type; typedef typename Endpoint::unlink_reason unlink_reason; typedef typename Endpoint::id_type id_type; virtual void link_failed(tag_type, id_type a1) = 0; virtual void handle(tag_type, link_type& a1, inbound_ptr a2) = 0; virtual void unlink(tag_type, link_type& a1, unlink_reason a2) = 0; void link_failed(id_type a1) { this->link_failed(tag_type(), a1); } void handle(link_type& a1, inbound_ptr a2) { this->handle(tag_type(), a1, a2); } void unlink(link_type& a1, unlink_reason a2) { this->unlink(tag_type(), a1, a2); } friend tagged_endpoint* that(tagged_endpoint* p, tag_type) { return p; } }; template struct tagged_client : tagged_endpoint {}; template struct tagged_server : tagged_endpoint {}; //////////////////////////////////////////////////////////////////////////////////////////////// } // namespace detail //////////////////////////////////////////////////////////////////////////////////////////////// } // namespace textrpc //////////////////////////////////////////////////////////////////////////////////////////////// #endif // TRANSPORT_H