// -*- C++ -*- //============================================================================= /** * @file Acceptor.h * * @author Douglas C. Schmidt */ //============================================================================= #ifndef ACE_ACCEPTOR_H #define ACE_ACCEPTOR_H #include /**/ "ace/pre.h" #include "ace/Service_Object.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "ace/Strategies_T.h" #include "ace/Synch_Options.h" ACE_BEGIN_VERSIONED_NAMESPACE_DECL /** * @class ACE_Acceptor * * @brief Abstract factory for creating a service handler * (SVC_HANDLER), accepting into the SVC_HANDLER, and * activating the SVC_HANDLER. * * Implements the basic strategy for passively establishing * connections with clients. An ACE_Acceptor inherits from * ACE_Service_Object, which in turn inherits from ACE_Event_Handler. * This enables the ACE_Reactor to dispatch the ACE_Acceptor's * handle_input method when connection events occur. The handle_input * method performs the ACE_Acceptor's default creation, connection * establishment, and service activation strategies. These strategies * can be overridden by subclasses individually or as a group. * * An ACE_Acceptor is parameterized by concrete types that conform to * the interfaces of SVC_HANDLER and PEER_ACCEPTOR described below. * * @tparam SVC_HANDLER The name of the concrete type that performs the * application-specific service. The SVC_HANDLER typically * inherits from ACE_Svc_Handler. @see Svc_Handler.h. * * @tparam PEER_ACCEPTOR The name of the class that implements the * PEER_ACCEPTOR endpoint (e.g., ACE_SOCK_Acceptor) to * passively establish connections. A PEER_ACCEPTOR * implementation must provide a PEER_STREAM and PEER_ADDR * trait to identify the type of stream (e.g., * ACE_SOCK_Stream) and type of address (e.g., ACE_INET_Addr) * used by the endpoint. */ template class ACE_Acceptor : public ACE_Service_Object { public: // Useful STL-style traits. typedef typename PEER_ACCEPTOR::PEER_ADDR addr_type; typedef PEER_ACCEPTOR acceptor_type; typedef SVC_HANDLER handler_type; typedef typename SVC_HANDLER::stream_type stream_type; /// "Do-nothing" constructor. ACE_Acceptor (ACE_Reactor * = 0, int use_select = ACE_DEFAULT_ACCEPTOR_USE_SELECT); /** * Open the contained @c PEER_ACCEPTOR object to begin listening, and * register with the specified reactor for accept events. An * acceptor can only listen to one port at a time, so make sure to * @c close() the acceptor before calling @c open() again. * * The @c PEER_ACCEPTOR handle is put into non-blocking mode as a * safeguard against the race condition that can otherwise occur * between the time when the passive-mode socket handle is "ready" * and when the actual @c accept() call is made. During this * interval, the client can shutdown the connection, in which case, * the @c accept() call can hang. * * @param local_addr The address to listen at. * @param reactor Pointer to the ACE_Reactor instance to register * this object with. The default is the singleton. * @param flags Flags to control what mode an accepted socket * will be put into after it is accepted. The only * legal value for this argument is @c ACE_NONBLOCK, * which enables non-blocking mode on the accepted * peer stream object in @c SVC_HANDLER. The default * is 0. * @param use_select Affects behavior when called back by the reactor * when a connection can be accepted. If non-zero, * this object will accept all pending connections, * instead of just the one that triggered the reactor * callback. Uses ACE_OS::select() internally to * detect any remaining acceptable connections. * The default is 1. * @param reuse_addr Passed to the @c PEER_ACCEPTOR::open() method with * @p local_addr. Generally used to request that the * OS allow reuse of the listen port. The default is 1. */ ACE_Acceptor (const typename PEER_ACCEPTOR::PEER_ADDR &local_addr, ACE_Reactor *reactor = ACE_Reactor::instance (), int flags = 0, int use_select = ACE_DEFAULT_ACCEPTOR_USE_SELECT, int reuse_addr = 1); /** * Open the contained @c PEER_ACCEPTOR object to begin listening, and * register with the specified reactor for accept events. An * acceptor can only listen to one port at a time, so make sure to * @c close() the acceptor before calling @c open() again. * * The @c PEER_ACCEPTOR handle is put into non-blocking mode as a * safeguard against the race condition that can otherwise occur * between the time when the passive-mode socket handle is "ready" * and when the actual @c accept() call is made. During this * interval, the client can shutdown the connection, in which case, * the @c accept() call can hang. * * @param local_addr The address to listen at. * @param reactor Pointer to the ACE_Reactor instance to register * this object with. The default is the singleton. * @param flags Flags to control what mode an accepted socket * will be put into after it is accepted. The only * legal value for this argument is @c ACE_NONBLOCK, * which enables non-blocking mode on the accepted * peer stream object in @c SVC_HANDLER. The default * is 0. * @param use_select Affects behavior when called back by the reactor * when a connection can be accepted. If non-zero, * this object will accept all pending connections, * instead of just the one that triggered the reactor * callback. Uses ACE_OS::select() internally to * detect any remaining acceptable connections. * The default is 1. * @param reuse_addr Passed to the @c PEER_ACCEPTOR::open() method with * @p local_addr. Generally used to request that the * OS allow reuse of the listen port. The default is 1. * * @retval 0 Success * @retval -1 Failure, @c errno contains an error code. */ virtual int open (const typename PEER_ACCEPTOR::PEER_ADDR &local_addr, ACE_Reactor *reactor = ACE_Reactor::instance (), int flags = 0, int use_select = ACE_DEFAULT_ACCEPTOR_USE_SELECT, int reuse_addr = 1); /// Close down the Acceptor's resources. virtual ~ACE_Acceptor (); /// Return the underlying PEER_ACCEPTOR object. virtual operator PEER_ACCEPTOR &() const; /// Return the underlying PEER_ACCEPTOR object. virtual PEER_ACCEPTOR &acceptor () const; /// Returns the listening acceptor's {ACE_HANDLE}. virtual ACE_HANDLE get_handle () const; /// Close down the Acceptor virtual int close (); /// In the event that an accept fails, this method will be called and /// the return value will be returned from handle_input(). virtual int handle_accept_error (); /// Dump the state of an object. void dump () const; /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; protected: // = The following three methods define the Acceptor's strategies // for creating, accepting, and activating SVC_HANDLER's, // respectively. /** * Bridge method for creating a SVC_HANDLER. The default is to * create a new {SVC_HANDLER} if {sh} == 0, else {sh} is unchanged. * However, subclasses can override this policy to perform * SVC_HANDLER creation in any way that they like (such as creating * subclass instances of SVC_HANDLER, using a singleton, dynamically * linking the handler, etc.). Returns -1 on failure, else 0. */ virtual int make_svc_handler (SVC_HANDLER *&sh); /** * Bridge method for accepting the new connection into the * @a svc_handler. The default behavior delegates to the * PEER_ACCEPTOR::accept. */ virtual int accept_svc_handler (SVC_HANDLER *svc_handler); /** * Bridge method for activating a @a svc_handler with the appropriate * concurrency strategy. The default behavior of this method is to * activate the SVC_HANDLER by calling its open() method (which * allows the SVC_HANDLER to define its own concurrency strategy). * However, subclasses can override this strategy to do more * sophisticated concurrency activations (such as making the * SVC_HANDLER as an "active object" via multi-threading or * multi-processing). */ virtual int activate_svc_handler (SVC_HANDLER *svc_handler); // = Demultiplexing hooks. /// Perform termination activities when {this} is removed from the /// {reactor}. virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK); /// Accepts all pending connections from clients, and creates and /// activates SVC_HANDLERs. virtual int handle_input (ACE_HANDLE); // = Dynamic linking hooks. /// Default version does no work and returns -1. Must be overloaded /// by application developer to do anything meaningful. virtual int init (int argc, ACE_TCHAR *argv[]); /// Calls {handle_close}. virtual int fini (); /// Default version returns address info in {buf}. virtual int info (ACE_TCHAR **buf, size_t) const; public: // = Service management hooks. /// This method calls {Reactor::suspend}. virtual int suspend (); /// This method calls {Reactor::resume}. virtual int resume (); protected: /// Concrete factory for accepting connections from clients... PEER_ACCEPTOR peer_acceptor_; /// Needed to reopen the socket if {accept} fails. typename PEER_ACCEPTOR::PEER_ADDR peer_acceptor_addr_; /** * Flags that indicate how {SVC_HANDLER}'s should be initialized * prior to being activated. Right now, the only flag that is * processed is {ACE_NONBLOCK}, which enabled non-blocking I/O on * the {SVC_HANDLER} when it is opened. */ int flags_; /// Flag that indicates whether it shall use {select} in the /// {accept}-loop. int use_select_; /// Needed to reopen the socket if {accept} fails. int reuse_addr_; }; /** * @class ACE_Strategy_Acceptor * * @brief Abstract factory for creating a service handler * (SVC_HANDLER), accepting into the SVC_HANDLER, and activating * the SVC_HANDLER. * * Implements a flexible and extensible set of strategies for * passively establishing connections with clients. There are * three main strategies: (1) creating a SVC_HANDLER, (2) * passively accepting a new connection from a client into the * SVC_HANDLER, and (3) activating the SVC_HANDLER with a * particular concurrency mechanism. */ template class ACE_Strategy_Acceptor : public ACE_Acceptor { public: // Useful STL-style traits. typedef ACE_Creation_Strategy creation_strategy_type; typedef ACE_Accept_Strategy accept_strategy_type; typedef ACE_Concurrency_Strategy concurrency_strategy_type; typedef ACE_Scheduling_Strategy scheduling_strategy_type; typedef ACE_Acceptor base_type; // = Define some useful (old style) traits. typedef ACE_Creation_Strategy CREATION_STRATEGY; typedef ACE_Accept_Strategy ACCEPT_STRATEGY; typedef ACE_Concurrency_Strategy CONCURRENCY_STRATEGY; typedef ACE_Scheduling_Strategy SCHEDULING_STRATEGY; /// Default constructor. ACE_Strategy_Acceptor (const ACE_TCHAR service_name[] = 0, const ACE_TCHAR service_description[] = 0, int use_select = ACE_DEFAULT_ACCEPTOR_USE_SELECT, int reuse_addr = 1); /** * Initialize the appropriate strategies for creation, passive * connection acceptance, and concurrency, and then register {this} * with the Reactor and listen for connection requests at the * designated {local_addr}. */ ACE_Strategy_Acceptor (const typename PEER_ACCEPTOR::PEER_ADDR &local_addr, ACE_Reactor * = ACE_Reactor::instance (), ACE_Creation_Strategy * = 0, ACE_Accept_Strategy * = 0, ACE_Concurrency_Strategy * = 0, ACE_Scheduling_Strategy * = 0, const ACE_TCHAR service_name[] = 0, const ACE_TCHAR service_description[] = 0, int use_select = ACE_DEFAULT_ACCEPTOR_USE_SELECT, int reuse_addr = 1); /** * Open the contained @c PEER_ACCEPTOR object to begin listening, and * register with the specified reactor for accept events. * * The @c PEER_ACCEPTOR handle is put into non-blocking mode as a * safeguard against the race condition that can otherwise occur * between the time when the passive-mode socket handle is "ready" * and when the actual @c accept call is made. During this * interval, the client can shutdown the connection, in which case, * the {accept} call can hang. * * @param local_addr The address to listen at. * @param reactor Pointer to the ACE_Reactor instance to register * this object with. The default is the singleton. * @param flags Flags to control what mode an accepted socket * will be put into after it is accepted. The only * legal value for this argument is @c ACE_NONBLOCK, * which enables non-blocking mode on the accepted * peer stream object in @c SVC_HANDLER. The default * is 0. * @param use_select Affects behavior when called back by the reactor * when a connection can be accepted. If non-zero, * this object will accept all pending connections, * instead of just the one that triggered the reactor * callback. Uses ACE_OS::select() internally to * detect any remaining acceptable connections. * The default is 1. * @param reuse_addr Passed to the @c PEER_ACCEPTOR::open() method with * @p local_addr. Generally used to request that the * OS allow reuse of the listen port. The default is 1. * * @retval 0 Success * @retval -1 Failure, @c errno contains an error code. */ virtual int open (const typename PEER_ACCEPTOR::PEER_ADDR &local_addr, ACE_Reactor *reactor, int flags = 0, int use_select = ACE_DEFAULT_ACCEPTOR_USE_SELECT, int reuse_addr = 1); /** * Initialize the appropriate strategies for creation, passive * connection acceptance, and concurrency, and then register {this} * with the Reactor and listen for connection requests at the * designated {local_addr}. */ virtual int open (const typename PEER_ACCEPTOR::PEER_ADDR &, ACE_Reactor * = ACE_Reactor::instance (), ACE_Creation_Strategy * = 0, ACE_Accept_Strategy * =0, ACE_Concurrency_Strategy * = 0, ACE_Scheduling_Strategy * = 0, const ACE_TCHAR *service_name = 0, const ACE_TCHAR *service_description = 0, int use_select = ACE_DEFAULT_ACCEPTOR_USE_SELECT, int reuse_addr = 1); /// Close down the Strategy_Acceptor's resources. virtual ~ACE_Strategy_Acceptor (); /// Return the underlying PEER_ACCEPTOR object. virtual operator PEER_ACCEPTOR &() const; /// Return the underlying PEER_ACCEPTOR object. virtual PEER_ACCEPTOR &acceptor () const; /// Returns the listening acceptor's {ACE_HANDLE}. virtual ACE_HANDLE get_handle () const; /// Dump the state of an object. void dump () const; /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; // = Service management hooks. /// This method delegates to the {Scheduling_Strategy}'s {suspend} /// method. virtual int suspend (); /// This method delegates to the {Scheduling_Strategy}'s {resume} /// method. virtual int resume (); protected: /// Calls {handle_close} when dynamically unlinked. virtual int fini (); /// Default version returns address info in {buf}. virtual int info (ACE_TCHAR **buf, size_t) const; // = The following three methods define the {Acceptor}'s strategies // for creating, accepting, and activating {SVC_HANDLER}'s, // respectively. /** * Bridge method for creating a {SVC_HANDLER}. The strategy for * creating a {SVC_HANDLER} are configured into the Acceptor via * it's {creation_strategy_}. The default is to create a new * {SVC_HANDLER} if {sh} == 0, else {sh} is unchanged. However, * subclasses can override this policy to perform {SVC_HANDLER} * creation in any way that they like (such as creating subclass * instances of {SVC_HANDLER}, using a singleton, dynamically * linking the handler, etc.). Returns -1 on failure, else 0. */ virtual int make_svc_handler (SVC_HANDLER *&); /** * Bridge method for accepting the new connection into the * {SVC_HANDLER}. The default behavior delegates to the * {PEER_ACCEPTOR::accept} in the {Acceptor_Strategy}. */ virtual int accept_svc_handler (SVC_HANDLER *svc_handler); /** * Bridge method for activating a {SVC_HANDLER} with the appropriate * concurrency strategy. The default behavior of this method is to * activate the {SVC_HANDLER} by calling its {open} method (which * allows the {SVC_HANDLER} to define its own concurrency strategy). * However, subclasses can override this strategy to do more * sophisticated concurrency activations (such as creating the * {SVC_HANDLER} as an "active object" via multi-threading or * multi-processing). */ virtual int activate_svc_handler (SVC_HANDLER *svc_handler); // = Demultiplexing hooks. /// Perform termination activities when {this} is removed from the /// {Reactor}. virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK); /// Handle SIGINT. virtual int handle_signal (int signum, siginfo_t *, ucontext_t *); // = These data members are "logically private" but are put in the // protected part in case subclasses want to access them. // = Strategy objects. /// Creation strategy for an Acceptor. CREATION_STRATEGY *creation_strategy_; /// true if {Acceptor} created the creation strategy and thus should /// delete it, else false. bool delete_creation_strategy_; /// Accept strategy for an {Acceptor}. ACCEPT_STRATEGY *accept_strategy_; /// true if {Acceptor} created the accept strategy and thus should delete /// it, else false. bool delete_accept_strategy_; /// Concurrency strategy for an {Acceptor}. CONCURRENCY_STRATEGY *concurrency_strategy_; /// true if {Acceptor} created the concurrency strategy and thus should /// delete it, else false. bool delete_concurrency_strategy_; /// Scheduling strategy for an {Acceptor}. SCHEDULING_STRATEGY *scheduling_strategy_; /// true if {Acceptor} created the scheduling strategy and thus should /// delete it, else false. bool delete_scheduling_strategy_; // = Service information objects. /// Name of the service. ACE_TCHAR *service_name_; /// Description of the service. ACE_TCHAR *service_description_; /// Address that the {Strategy_Acceptor} uses to listen for /// connections. typename PEER_ACCEPTOR::PEER_ADDR service_addr_; }; /** * @class ACE_Oneshot_Acceptor * * @brief Generic factory for passively connecting clients and creating * exactly one service handler of the type SVC_HANDLER specified in the * template. * * This class works similarly to the regular ACE_Acceptor, but * with the following differences: * -# ACE_Oneshot_Acceptor doesn't automatically register itself with the * ACE_Reactor; the caller is expected to call the accept() method * directly. Since a later call to accept() may require a reactor, * the constructor and open() methods both accept an ACE_Reactor pointer * which is saved in case it's needed in accept(). * -# ACE_Oneshot_Acceptor doesn't need an ACE_Creation_Strategy (because * the user supplies the SVC_HANDLER) or an ACE_Accept_Strategy (because * this class only accepts one connection and then removes all traces of * itself from the ACE_Reactor if it was registered for asynchronous * accepts). * * The usage model for ACE_Oneshot_Acceptor is: * - Instantiate an object and establish its local address to listen at. * This can be accomplished using either the address-accepting constructor * (but there's no error indication) or the default constructor followed * by a call to open(). * - Call the accept() method. This will attempt to accept a connection * immediately. If there is no immediately available connection to accept, * behavior is governed by the ACE_Synch_Options argument passed to open(). */ template class ACE_Oneshot_Acceptor : public ACE_Service_Object { public: // Useful STL-style traits. typedef typename PEER_ACCEPTOR::PEER_ADDR addr_type; typedef PEER_ACCEPTOR acceptor_type; typedef SVC_HANDLER handler_type; typedef typename SVC_HANDLER::stream_type stream_type; /// Constructor. ACE_Oneshot_Acceptor (); /** * Initialize the appropriate strategies for concurrency and then * open the acceptor at the designated @a local_addr. Note * that unlike ACE_Acceptor and ACE_Strategy_Acceptor, this * method does NOT register this acceptor with the @a reactor at * this point -- the @a reactor parameter is saved in case it's * needed later. */ ACE_Oneshot_Acceptor (const typename PEER_ACCEPTOR::PEER_ADDR &local_addr, ACE_Reactor *reactor = ACE_Reactor::instance (), ACE_Concurrency_Strategy * = 0); /** * Initialize the appropriate strategies for concurrency and then * open the acceptor at the designated @a local_addr. Note * that unlike ACE_Acceptor and ACE_Strategy_Acceptor, this * method does NOT register this acceptor with the @a reactor at * this point -- the @a reactor parameter is saved in case it's * needed later. */ int open (const typename PEER_ACCEPTOR::PEER_ADDR &, ACE_Reactor *reactor = ACE_Reactor::instance (), ACE_Concurrency_Strategy * = 0); /// Close down the {Oneshot_Acceptor}. virtual ~ACE_Oneshot_Acceptor (); // = Explicit factory operation. /// Create a {SVC_HANDLER}, accept the connection into the /// {SVC_HANDLER}, and activate the {SVC_HANDLER}. virtual int accept (SVC_HANDLER * = 0, typename PEER_ACCEPTOR::PEER_ADDR *remote_addr = 0, const ACE_Synch_Options &synch_options = ACE_Synch_Options::defaults, bool restart = true, bool reset_new_handle = false); /// Cancel a oneshot acceptor that was started asynchronously. virtual int cancel (); /// Return the underlying {PEER_ACCEPTOR} object. virtual operator PEER_ACCEPTOR &() const; /// Return the underlying {PEER_ACCEPTOR} object. virtual PEER_ACCEPTOR &acceptor () const; /// Close down the {Oneshot_Acceptor}. virtual int close (); /// Dump the state of an object. void dump () const; /// Declare the dynamic allocation hooks. ACE_ALLOC_HOOK_DECLARE; protected: /** * Bridge method for activating a {svc_handler} with the appropriate * concurrency strategy. Default behavior is to activate the * {SVC_HANDLER} as a "passive object." However, subclasses can * override this strategy to do more sophisticated concurrency * activations (such as creating the {SVC_HANDLER} as an "active * object" via multi-threading or multi-processing). */ virtual int activate_svc_handler (SVC_HANDLER *svc_handler); /// Factors out the code shared between the {accept} and /// {handle_input} methods. int shared_accept (SVC_HANDLER *svc_handler, typename PEER_ACCEPTOR::PEER_ADDR *remote_addr, ACE_Time_Value *timeout, bool restart, bool reset_new_handle); // = Demultiplexing hooks. /// Returns the listening acceptor's {ACE_HANDLE}. virtual ACE_HANDLE get_handle () const; /// Perform termination activities when {this} is removed from the /// {reactor}. virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE, ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK); /// Accept one connection from a client and activates the /// SVC_HANDLER. virtual int handle_input (ACE_HANDLE); /// Called when an acceptor times out... virtual int handle_timeout (const ACE_Time_Value &tv, const void *arg); // = Dynamic linking hooks. /// Default version does no work and returns -1. Must be overloaded /// by application developer to do anything meaningful. virtual int init (int argc, ACE_TCHAR *argv[]); /// Default version does no work and returns -1. Must be overloaded /// by application developer to do anything meaningful. virtual int fini (); /// Default version returns address info in {buf}. virtual int info (ACE_TCHAR **, size_t) const; // = Service management hooks. /// Default version does no work and returns -1. Must be overloaded /// by application developer to do anything meaningful. virtual int suspend (); /// Default version does no work and returns -1. Must be overloaded /// by application developer to do anything meaningful. virtual int resume (); private: /** * Insert ourselves into the {ACE_Reactor} so that we can continue * accepting this connection asynchronously. This method should NOT * be called by developers directly. */ int register_handler (SVC_HANDLER *svc_handler, const ACE_Synch_Options &options, bool restart); /// Hold the svc_handler_ across asynchrony boundaries. SVC_HANDLER *svc_handler_; /// Hold the restart flag across asynchrony boundaries. bool restart_; /// Factory that establishes connections passively. PEER_ACCEPTOR peer_acceptor_; /// Concurrency strategy for an Acceptor. ACE_Concurrency_Strategy *concurrency_strategy_; /// true if Acceptor created the concurrency strategy and thus should /// delete it, else false. bool delete_concurrency_strategy_; }; ACE_END_VERSIONED_NAMESPACE_DECL #include "ace/Acceptor.cpp" #include /**/ "ace/post.h" #endif /* ACE_ACCEPTOR_H */