mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2025-11-29 17:38:24 +08:00
1255 lines
43 KiB
C++
1255 lines
43 KiB
C++
#ifndef ACE_ACCEPTOR_CPP
|
|
#define ACE_ACCEPTOR_CPP
|
|
|
|
#include "ace/ACE.h"
|
|
|
|
#if !defined (ACE_LACKS_PRAGMA_ONCE)
|
|
# pragma once
|
|
#endif /* ACE_LACKS_PRAGMA_ONCE */
|
|
|
|
#include "ace/Acceptor.h"
|
|
#include "ace/Svc_Handler.h"
|
|
#include "ace/WFMO_Reactor.h"
|
|
#include "ace/OS_NS_stdio.h"
|
|
#include "ace/OS_NS_string.h"
|
|
|
|
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
|
|
|
|
ACE_ALLOC_HOOK_DEFINE(ACE_Acceptor)
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> void
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::dump (void) const
|
|
{
|
|
#if defined (ACE_HAS_DUMP)
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::dump");
|
|
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
|
|
this->peer_acceptor_.dump ();
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
|
|
#endif /* ACE_HAS_DUMP */
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR>
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::operator PEER_ACCEPTOR & () const
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::operator PEER_ACCEPTOR &");
|
|
return (PEER_ACCEPTOR &) this->peer_acceptor_;
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> PEER_ACCEPTOR &
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::acceptor (void) const
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::acceptor");
|
|
return const_cast<PEER_ACCEPTOR &> (this->peer_acceptor_);
|
|
}
|
|
|
|
// Returns ACE_HANDLE of the underlying Acceptor_Strategy.
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> ACE_HANDLE
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::get_handle (void) const
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::get_handle");
|
|
return this->peer_acceptor_.get_handle ();
|
|
}
|
|
|
|
// 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>.
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::open
|
|
(const typename PEER_ACCEPTOR::PEER_ADDR &local_addr,
|
|
ACE_Reactor *reactor,
|
|
int flags,
|
|
int use_select,
|
|
int reuse_addr)
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::open");
|
|
this->flags_ = flags;
|
|
this->use_select_ = use_select;
|
|
this->reuse_addr_ = reuse_addr;
|
|
this->peer_acceptor_addr_ = local_addr;
|
|
|
|
// Must supply a valid Reactor to Acceptor::open()...
|
|
|
|
if (reactor == 0)
|
|
{
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
// Open the underlying PEER_ACCEPTOR.
|
|
if (this->peer_acceptor_.open (local_addr, reuse_addr) == -1)
|
|
return -1;
|
|
|
|
// Set the peer acceptor's handle into non-blocking mode. This is a
|
|
// safe-guard against the race condition that can otherwise occur
|
|
// between the time when <select> indicates that a passive-mode
|
|
// socket handle is "ready" and when we call <accept>. During this
|
|
// interval, the client can shutdown the connection, in which case,
|
|
// the <accept> call can hang!
|
|
(void) this->peer_acceptor_.enable (ACE_NONBLOCK);
|
|
|
|
int const result = reactor->register_handler (this,
|
|
ACE_Event_Handler::ACCEPT_MASK);
|
|
if (result != -1)
|
|
this->reactor (reactor);
|
|
else
|
|
this->peer_acceptor_.close ();
|
|
|
|
return result;
|
|
}
|
|
|
|
// Simple constructor.
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR>
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::ACE_Acceptor (ACE_Reactor *reactor,
|
|
int use_select)
|
|
:flags_ (0),
|
|
use_select_ (use_select),
|
|
reuse_addr_ (1)
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::ACE_Acceptor");
|
|
|
|
this->reactor (reactor);
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR>
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::ACE_Acceptor
|
|
(const typename PEER_ACCEPTOR::PEER_ADDR &addr,
|
|
ACE_Reactor *reactor,
|
|
int flags,
|
|
int use_select,
|
|
int reuse_addr)
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::ACE_Acceptor");
|
|
|
|
if (this->open (addr,
|
|
reactor,
|
|
flags,
|
|
use_select,
|
|
reuse_addr) == -1)
|
|
ACELIB_ERROR ((LM_ERROR,
|
|
ACE_TEXT ("%p\n"),
|
|
ACE_TEXT ("ACE_Acceptor::ACE_Acceptor")));
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR>
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::~ACE_Acceptor (void)
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::~ACE_Acceptor");
|
|
this->handle_close ();
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::fini (void)
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::fini");
|
|
return ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::handle_close ();
|
|
}
|
|
|
|
// Hook called by the explicit dynamic linking facility.
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::init (int, ACE_TCHAR *[])
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::init");
|
|
return -1;
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::info (ACE_TCHAR **strp,
|
|
size_t length) const
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::info");
|
|
ACE_TCHAR buf[BUFSIZ];
|
|
ACE_TCHAR addr_str[BUFSIZ];
|
|
typename PEER_ACCEPTOR::PEER_ADDR addr;
|
|
|
|
if (this->acceptor ().get_local_addr (addr) == -1)
|
|
return -1;
|
|
else if (addr.addr_to_string (addr_str, sizeof addr_str) == -1)
|
|
return -1;
|
|
|
|
ACE_OS::sprintf (buf,
|
|
ACE_TEXT ("%s\t %s %s"),
|
|
ACE_TEXT ("ACE_Acceptor"),
|
|
addr_str,
|
|
ACE_TEXT ("# acceptor factory\n"));
|
|
|
|
if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
|
|
return -1;
|
|
else
|
|
ACE_OS::strsncpy (*strp, buf, length);
|
|
return static_cast<int> (ACE_OS::strlen (buf));
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::suspend (void)
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::suspend");
|
|
return this->reactor ()->suspend_handler (this);
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::resume (void)
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::resume");
|
|
return this->reactor ()->resume_handler (this);
|
|
}
|
|
|
|
// Perform termination activities when <this> is removed from the
|
|
// <reactor>.
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::close (void)
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::close");
|
|
return this->handle_close ();
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::handle_accept_error (void)
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::handle_accept_error");
|
|
return 0;
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::handle_close (ACE_HANDLE,
|
|
ACE_Reactor_Mask)
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::handle_close");
|
|
// Guard against multiple closes.
|
|
if (this->reactor () != 0)
|
|
{
|
|
ACE_HANDLE handle = this->get_handle ();
|
|
|
|
this->reactor ()->remove_handler
|
|
(handle,
|
|
// We must pass the DONT_CALL flag here to avoid infinite
|
|
// recursion.
|
|
ACE_Event_Handler::ACCEPT_MASK | ACE_Event_Handler::DONT_CALL);
|
|
|
|
// Shut down the listen socket to recycle the handles.
|
|
if (this->peer_acceptor_.close () == -1)
|
|
ACELIB_ERROR ((LM_ERROR,
|
|
ACE_TEXT ("close\n")));
|
|
// Set the Reactor to 0 so that we don't try to close down
|
|
// again.
|
|
this->reactor (0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// 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.
|
|
// However, subclasses can override this strategy 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.).
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::make_svc_handler (SVC_HANDLER *&sh)
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::make_svc_handler");
|
|
|
|
if (sh == 0)
|
|
ACE_NEW_RETURN (sh,
|
|
SVC_HANDLER,
|
|
-1);
|
|
|
|
// Set the reactor of the newly created <SVC_HANDLER> to the same
|
|
// reactor that this <ACE_Acceptor> is using.
|
|
sh->reactor (this->reactor ());
|
|
return 0;
|
|
}
|
|
|
|
// Bridge method for accepting the new connection into the
|
|
// <svc_handler>. The default behavior delegates to the
|
|
// <PEER_ACCEPTOR::accept> in the Acceptor_Strategy.
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::accept_svc_handler
|
|
(SVC_HANDLER *svc_handler)
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::accept_svc_handler");
|
|
|
|
// Try to find out if the implementation of the reactor that we are
|
|
// using requires us to reset the event association for the newly
|
|
// created handle. This is because the newly created handle will
|
|
// inherit the properties of the listen handle, including its event
|
|
// associations.
|
|
|
|
ACE_Reactor *reactor = this->reactor ();
|
|
bool reset_new_handle;
|
|
|
|
if (reactor)
|
|
{
|
|
reset_new_handle = reactor->uses_event_associations ();
|
|
}
|
|
else
|
|
{
|
|
// Acceptor is closed, so reject this call
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
if (this->acceptor ().accept (svc_handler->peer (), // stream
|
|
0, // remote address
|
|
0, // timeout
|
|
true, // restart
|
|
reset_new_handle // reset new handler
|
|
) == -1)
|
|
{
|
|
// Ensure that errno is preserved in case the svc_handler
|
|
// close() method resets it
|
|
ACE_Errno_Guard error(errno);
|
|
|
|
// Close down handler to avoid memory leaks.
|
|
svc_handler->close (CLOSE_DURING_NEW_CONNECTION);
|
|
|
|
return -1;
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
// 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).
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::activate_svc_handler
|
|
(SVC_HANDLER *svc_handler)
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::activate_svc_handler");
|
|
|
|
int result = 0;
|
|
|
|
// See if we should enable non-blocking I/O on the <svc_handler>'s
|
|
// peer.
|
|
if (ACE_BIT_ENABLED (this->flags_,
|
|
ACE_NONBLOCK))
|
|
{
|
|
if (svc_handler->peer ().enable (ACE_NONBLOCK) == -1)
|
|
result = -1;
|
|
}
|
|
// Otherwise, make sure it's disabled by default.
|
|
else if (svc_handler->peer ().disable (ACE_NONBLOCK) == -1)
|
|
result = -1;
|
|
|
|
if (result == 0 && svc_handler->open ((void *) this) == -1)
|
|
result = -1;
|
|
|
|
if (result == -1)
|
|
// The connection was already made; so this close is a "normal" close
|
|
// operation.
|
|
svc_handler->close (NORMAL_CLOSE_OPERATION);
|
|
|
|
return result;
|
|
}
|
|
|
|
// Template Method that makes a SVC_HANDLER (using the appropriate
|
|
// creation strategy), accept the connection into the SVC_HANDLER, and
|
|
// then activate the SVC_HANDLER.
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::handle_input (ACE_HANDLE listener)
|
|
{
|
|
ACE_TRACE ("ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::handle_input");
|
|
|
|
// Default is "timeout (0, 0)," which means "poll."
|
|
ACE_Time_Value timeout;
|
|
|
|
// Accept connections from clients. Note that a loop is used for two
|
|
// reasons:
|
|
//
|
|
// 1. It allows us to accept all pending connections without an
|
|
// extra trip through the ACE_Reactor and without having to use
|
|
// non-blocking I/O...
|
|
//
|
|
// 2. It allows the TLI_SAP::ACE_Acceptor class to work correctly (don't
|
|
// ask -- TLI is *horrible*...).
|
|
|
|
// Ensure that errno is preserved in case the ACE::handle_read_ready()
|
|
// method resets it in the loop bellow. We are actually supposed to
|
|
// ignore any errors from this loop, hence the return 0 following it.
|
|
ACE_Errno_Guard error (errno);
|
|
|
|
// @@ What should we do if any of the substrategies fail? Right
|
|
// now, we just print out a diagnostic message if <ACE::debug>
|
|
// returns > 0 and return 0 (which means that the Acceptor remains
|
|
// registered with the Reactor)...
|
|
do
|
|
{
|
|
// Create a service handler, using the appropriate creation
|
|
// strategy.
|
|
|
|
SVC_HANDLER *svc_handler = 0;
|
|
|
|
if (this->make_svc_handler (svc_handler) == -1)
|
|
{
|
|
if (ACE::debug ())
|
|
{
|
|
ACELIB_DEBUG ((LM_DEBUG,
|
|
ACE_TEXT ("%p\n"),
|
|
ACE_TEXT ("make_svc_handler")));
|
|
}
|
|
return 0;
|
|
}
|
|
// Accept connection into the Svc_Handler.
|
|
else if (this->accept_svc_handler (svc_handler) == -1)
|
|
{
|
|
// Note that <accept_svc_handler> closes the <svc_handler>
|
|
// on failure.
|
|
if (ACE::debug ())
|
|
{
|
|
ACELIB_DEBUG ((LM_DEBUG,
|
|
ACE_TEXT ("%p\n"),
|
|
ACE_TEXT ("accept_svc_handler")));
|
|
}
|
|
const int ret = this->handle_accept_error ();
|
|
if (ret == -1)
|
|
{
|
|
// Ensure that the errno from the above call propegates.
|
|
error = errno;
|
|
}
|
|
return ret;
|
|
}
|
|
// Activate the <svc_handler> using the designated concurrency
|
|
// strategy (note that this method becomes responsible for
|
|
// handling errors and freeing up the memory if things go
|
|
// awry...).
|
|
else if (this->activate_svc_handler (svc_handler) == -1)
|
|
{
|
|
// Note that <activate_svc_handler> closes the <svc_handler>
|
|
// on failure.
|
|
|
|
if (ACE::debug ())
|
|
{
|
|
ACELIB_DEBUG ((LM_DEBUG,
|
|
ACE_TEXT ("%p\n"),
|
|
ACE_TEXT ("activate_svc_handler")));
|
|
}
|
|
return 0;
|
|
}
|
|
// Now, check to see if there is another connection pending and
|
|
// break out of the loop if there is none.
|
|
} while (this->use_select_ &&
|
|
ACE::handle_read_ready (listener, &timeout) == 1);
|
|
return 0;
|
|
}
|
|
|
|
ACE_ALLOC_HOOK_DEFINE(ACE_Strategy_Acceptor)
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::suspend (void)
|
|
{
|
|
ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::suspend");
|
|
|
|
// First suspend the SVC_HANDLER's we've created.
|
|
if (this->scheduling_strategy_->suspend () == -1)
|
|
return -1;
|
|
else // Then suspend ourselves.
|
|
return ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::suspend ();
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::resume (void)
|
|
{
|
|
ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::resume");
|
|
|
|
// First resume ourselves.
|
|
if (ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::resume () == -1)
|
|
return -1;
|
|
else // Then resume the SVC_HANDLER's we've created.
|
|
return this->scheduling_strategy_->resume ();
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> void
|
|
ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::dump (void) const
|
|
{
|
|
#if defined (ACE_HAS_DUMP)
|
|
ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::dump");
|
|
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
|
|
ACE_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::dump ();
|
|
this->creation_strategy_->dump ();
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("delete_creation_strategy_ = %d"), delete_creation_strategy_));
|
|
this->accept_strategy_->dump ();
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("delete_accept_strategy_ = %d"), delete_accept_strategy_));
|
|
this->concurrency_strategy_->dump ();
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("delete_concurrency_strategy_ = %d"), delete_concurrency_strategy_));
|
|
this->scheduling_strategy_->dump ();
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("delete_scheduling_strategy_ = %d"), delete_scheduling_strategy_));
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nservice_name_ = %s"),
|
|
this->service_name_ == 0 ? ACE_TEXT ("<unknown>") : this->service_name_));
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nservice_description_ = %s"),
|
|
this->service_description_ == 0 ? ACE_TEXT ("<unknown>") : this->service_description_));
|
|
this->service_addr_.dump ();
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
|
|
#endif /* ACE_HAS_DUMP */
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> PEER_ACCEPTOR &
|
|
ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::acceptor (void) const
|
|
{
|
|
ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::acceptor");
|
|
return this->accept_strategy_->acceptor ();
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR>
|
|
ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::operator PEER_ACCEPTOR & () const
|
|
{
|
|
ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::operator PEER_ACCEPTOR &");
|
|
return this->accept_strategy_->acceptor ();
|
|
}
|
|
|
|
// Returns ACE_HANDLE of the underlying Acceptor_Strategy.
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> ACE_HANDLE
|
|
ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::get_handle (void) const
|
|
{
|
|
ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::get_handle");
|
|
return this->accept_strategy_->get_handle ();
|
|
}
|
|
|
|
// 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>.
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::open
|
|
(const typename PEER_ACCEPTOR::PEER_ADDR &local_addr,
|
|
ACE_Reactor *reactor,
|
|
int /* flags unused */,
|
|
int use_select,
|
|
int reuse_addr)
|
|
{
|
|
ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::open");
|
|
return this->open
|
|
(local_addr, reactor, 0, 0, 0, 0, 0, 0, use_select, reuse_addr);
|
|
}
|
|
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::open
|
|
(const typename PEER_ACCEPTOR::PEER_ADDR &local_addr,
|
|
ACE_Reactor *reactor,
|
|
ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
|
|
ACE_Accept_Strategy<SVC_HANDLER, PEER_ACCEPTOR> *acc_s,
|
|
ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
|
|
ACE_Scheduling_Strategy<SVC_HANDLER> *sch_s,
|
|
const ACE_TCHAR *service_name,
|
|
const ACE_TCHAR *service_description,
|
|
int use_select,
|
|
int reuse_addr)
|
|
{
|
|
ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::open");
|
|
|
|
if (this->service_name_ == 0 && service_name != 0)
|
|
ACE_ALLOCATOR_RETURN (this->service_name_,
|
|
ACE_OS::strdup (service_name),
|
|
-1);
|
|
if (this->service_description_ == 0 && service_description != 0)
|
|
ACE_ALLOCATOR_RETURN (this->service_description_,
|
|
ACE_OS::strdup (service_description),
|
|
-1);
|
|
this->reactor (reactor);
|
|
|
|
// Must supply a valid Reactor to Acceptor::open()...
|
|
if (reactor == 0)
|
|
{
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
// Initialize the creation strategy.
|
|
|
|
if (cre_s == 0)
|
|
{
|
|
ACE_NEW_RETURN (cre_s,
|
|
CREATION_STRATEGY,
|
|
-1);
|
|
this->delete_creation_strategy_ = true;
|
|
}
|
|
this->creation_strategy_ = cre_s;
|
|
|
|
// Initialize the accept strategy.
|
|
|
|
if (acc_s == 0)
|
|
{
|
|
ACE_NEW_RETURN (acc_s,
|
|
ACCEPT_STRATEGY (this->reactor ()),
|
|
-1);
|
|
this->delete_accept_strategy_ = true;
|
|
}
|
|
this->accept_strategy_ = acc_s;
|
|
|
|
if (this->accept_strategy_->open (local_addr, reuse_addr) == -1)
|
|
return -1;
|
|
|
|
// Set the peer acceptor's handle into non-blocking mode. This is a
|
|
// safe-guard against the race condition that can otherwise occur
|
|
// between the time when <select> indicates that a passive-mode
|
|
// socket handle is "ready" and when we call <accept>. During this
|
|
// interval, the client can shutdown the connection, in which case,
|
|
// the <accept> call can hang!
|
|
if (this->accept_strategy_->acceptor ().enable (ACE_NONBLOCK) != 0)
|
|
return -1;
|
|
|
|
// Initialize the concurrency strategy.
|
|
|
|
if (con_s == 0)
|
|
{
|
|
ACE_NEW_RETURN (con_s,
|
|
CONCURRENCY_STRATEGY,
|
|
-1);
|
|
this->delete_concurrency_strategy_ = true;
|
|
}
|
|
this->concurrency_strategy_ = con_s;
|
|
|
|
// Initialize the scheduling strategy.
|
|
|
|
if (sch_s == 0)
|
|
{
|
|
ACE_NEW_RETURN (sch_s,
|
|
SCHEDULING_STRATEGY,
|
|
-1);
|
|
this->delete_scheduling_strategy_ = true;
|
|
}
|
|
this->scheduling_strategy_ = sch_s;
|
|
|
|
this->use_select_ = use_select;
|
|
|
|
return this->reactor ()->register_handler
|
|
(this,
|
|
ACE_Event_Handler::ACCEPT_MASK);
|
|
}
|
|
|
|
// Simple constructor.
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR>
|
|
ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::ACE_Strategy_Acceptor
|
|
(const ACE_TCHAR service_name[],
|
|
const ACE_TCHAR service_description[],
|
|
int use_select,
|
|
int reuse_addr)
|
|
: creation_strategy_ (0),
|
|
delete_creation_strategy_ (false),
|
|
accept_strategy_ (0),
|
|
delete_accept_strategy_ (false),
|
|
concurrency_strategy_ (0),
|
|
delete_concurrency_strategy_ (false),
|
|
scheduling_strategy_ (0),
|
|
delete_scheduling_strategy_ (false),
|
|
service_name_ (0),
|
|
service_description_ (0)
|
|
{
|
|
ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::ACE_Strategy_Acceptor");
|
|
|
|
if (service_name != 0)
|
|
ACE_ALLOCATOR (this->service_name_,
|
|
ACE_OS::strdup (service_name));
|
|
if (service_description != 0)
|
|
ACE_ALLOCATOR (this->service_description_,
|
|
ACE_OS::strdup (service_description));
|
|
this->use_select_ = use_select;
|
|
this->reuse_addr_ = reuse_addr;
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR>
|
|
ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::ACE_Strategy_Acceptor
|
|
(const typename PEER_ACCEPTOR::PEER_ADDR &addr,
|
|
ACE_Reactor *reactor,
|
|
ACE_Creation_Strategy<SVC_HANDLER> *cre_s,
|
|
ACE_Accept_Strategy<SVC_HANDLER, PEER_ACCEPTOR> *acc_s,
|
|
ACE_Concurrency_Strategy<SVC_HANDLER> *con_s,
|
|
ACE_Scheduling_Strategy<SVC_HANDLER> *sch_s,
|
|
const ACE_TCHAR service_name[],
|
|
const ACE_TCHAR service_description[],
|
|
int use_select,
|
|
int reuse_addr)
|
|
: creation_strategy_ (0),
|
|
delete_creation_strategy_ (false),
|
|
accept_strategy_ (0),
|
|
delete_accept_strategy_ (false),
|
|
concurrency_strategy_ (0),
|
|
delete_concurrency_strategy_ (false),
|
|
scheduling_strategy_ (0),
|
|
delete_scheduling_strategy_ (false),
|
|
service_name_ (0),
|
|
service_description_ (0)
|
|
{
|
|
ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::ACE_Strategy_Acceptor");
|
|
|
|
if (this->open (addr,
|
|
reactor,
|
|
cre_s,
|
|
acc_s,
|
|
con_s,
|
|
sch_s,
|
|
service_name,
|
|
service_description,
|
|
use_select,
|
|
reuse_addr) == -1)
|
|
ACELIB_ERROR ((LM_ERROR,
|
|
ACE_TEXT ("%p\n"),
|
|
ACE_TEXT ("ACE_Strategy_Acceptor::ACE_Strategy_Acceptor")));
|
|
}
|
|
|
|
// Perform termination activities when <this> is removed from the
|
|
// <ACE_Reactor>.
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::handle_close (ACE_HANDLE,
|
|
ACE_Reactor_Mask)
|
|
{
|
|
ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::handle_close");
|
|
// Guard against multiple closes.
|
|
if (this->reactor () != 0)
|
|
{
|
|
ACE_HANDLE handle = this->get_handle ();
|
|
|
|
if (this->delete_creation_strategy_)
|
|
delete this->creation_strategy_;
|
|
this->delete_creation_strategy_ = false;
|
|
this->creation_strategy_ = 0;
|
|
|
|
if (this->delete_accept_strategy_)
|
|
delete this->accept_strategy_;
|
|
this->delete_accept_strategy_ = false;
|
|
this->accept_strategy_ = 0;
|
|
|
|
if (this->delete_concurrency_strategy_)
|
|
delete this->concurrency_strategy_;
|
|
this->delete_concurrency_strategy_ = false;
|
|
this->concurrency_strategy_ = 0;
|
|
|
|
if (this->delete_scheduling_strategy_)
|
|
delete this->scheduling_strategy_;
|
|
this->delete_scheduling_strategy_ = false;
|
|
this->scheduling_strategy_ = 0;
|
|
|
|
// We must use the <handle> obtained *before* we deleted the
|
|
// accept_strategy_...
|
|
|
|
this->reactor ()->remove_handler
|
|
(handle,
|
|
ACE_Event_Handler::ACCEPT_MASK | ACE_Event_Handler::DONT_CALL);
|
|
|
|
// Set the Reactor to 0 so that we don't try to close down
|
|
// again.
|
|
this->reactor (0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// 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>. However, subclasses can override this strategy 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.).
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::make_svc_handler (SVC_HANDLER *&sh)
|
|
{
|
|
ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::make_svc_handler");
|
|
return this->creation_strategy_->make_svc_handler (sh);
|
|
}
|
|
|
|
// Bridge method for accepting the new connection into the
|
|
// <svc_handler>. The default behavior delegates to the
|
|
// <Strategy_Acceptor::accept> in the Acceptor_Strategy.
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::accept_svc_handler
|
|
(SVC_HANDLER *svc_handler)
|
|
{
|
|
ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::accept_svc_handler");
|
|
return this->accept_strategy_->accept_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).
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::activate_svc_handler
|
|
(SVC_HANDLER *svc_handler)
|
|
{
|
|
ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::activate_svc_handler");
|
|
return this->concurrency_strategy_->activate_svc_handler
|
|
(svc_handler,
|
|
(void *) this);
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR>
|
|
ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::~ACE_Strategy_Acceptor (void)
|
|
{
|
|
ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::~ACE_Strategy_Acceptor");
|
|
ACE_OS::free ((void *) this->service_name_);
|
|
ACE_OS::free ((void *) this->service_description_);
|
|
this->handle_close ();
|
|
}
|
|
|
|
// Signal the server to shutdown gracefully.
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::handle_signal (int, siginfo_t *, ucontext_t *)
|
|
{
|
|
ACE_Reactor::instance()->end_reactor_event_loop ();
|
|
return 0;
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::info (ACE_TCHAR **strp,
|
|
size_t length) const
|
|
{
|
|
ACE_TRACE ("ACE_Strategy_Acceptor::info");
|
|
|
|
ACE_TCHAR buf[BUFSIZ];
|
|
ACE_TCHAR service_addr_str[BUFSIZ];
|
|
typename PEER_ACCEPTOR::PEER_ADDR addr;
|
|
|
|
if (this->acceptor ().get_local_addr (addr) == -1)
|
|
return -1;
|
|
else if (addr.addr_to_string (service_addr_str,
|
|
sizeof service_addr_str) == -1)
|
|
return -1;
|
|
|
|
// @@ Should add the protocol in...
|
|
ACE_OS::sprintf (buf,
|
|
ACE_TEXT ("%s\t %s #%s\n"),
|
|
this->service_name_ == 0
|
|
? ACE_TEXT ("<unknown>")
|
|
: this->service_name_,
|
|
service_addr_str,
|
|
this->service_description_ == 0
|
|
? ACE_TEXT ("<unknown>")
|
|
: this->service_description_);
|
|
|
|
if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
|
|
return -1;
|
|
else
|
|
ACE_OS::strsncpy (*strp, buf, length);
|
|
return static_cast<int> (ACE_OS::strlen (buf));
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::fini (void)
|
|
{
|
|
ACE_TRACE ("ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::fini");
|
|
return this->ACE_Strategy_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::handle_close ();
|
|
}
|
|
|
|
ACE_ALLOC_HOOK_DEFINE(ACE_Oneshot_Acceptor)
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> void
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::dump (void) const
|
|
{
|
|
#if defined (ACE_HAS_DUMP)
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::dump");
|
|
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nsvc_handler_ = %x"), this->svc_handler_));
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nrestart_ = %d"), this->restart_));
|
|
this->peer_acceptor_.dump ();
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("delete_concurrency_strategy_ = %d"),
|
|
delete_concurrency_strategy_));
|
|
this->concurrency_strategy_->dump ();
|
|
ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
|
|
#endif /* ACE_HAS_DUMP */
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::open
|
|
(const typename PEER_ACCEPTOR::PEER_ADDR &local_addr,
|
|
ACE_Reactor *reactor,
|
|
ACE_Concurrency_Strategy<SVC_HANDLER> *con_s)
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::open");
|
|
this->reactor (reactor);
|
|
|
|
// Initialize the concurrency strategy.
|
|
|
|
if (con_s == 0)
|
|
{
|
|
ACE_NEW_RETURN (con_s,
|
|
ACE_Concurrency_Strategy<SVC_HANDLER>,
|
|
-1);
|
|
this->delete_concurrency_strategy_ = true;
|
|
}
|
|
this->concurrency_strategy_ = con_s;
|
|
|
|
// Reuse the addr, even if it is already in use...!
|
|
return this->peer_acceptor_.open (local_addr, 1);
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR>
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::ACE_Oneshot_Acceptor (void)
|
|
: svc_handler_ (0),
|
|
restart_ (false),
|
|
concurrency_strategy_ (0),
|
|
delete_concurrency_strategy_ (false)
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::ACE_Oneshot_Acceptor");
|
|
this->reactor (0);
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR>
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::ACE_Oneshot_Acceptor
|
|
(const typename PEER_ACCEPTOR::PEER_ADDR &local_addr,
|
|
ACE_Reactor *reactor,
|
|
ACE_Concurrency_Strategy<SVC_HANDLER> *cs)
|
|
: svc_handler_ (0),
|
|
restart_ (false),
|
|
concurrency_strategy_ (0),
|
|
delete_concurrency_strategy_ (false)
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::ACE_Oneshot_Acceptor");
|
|
if (this->open (local_addr, reactor, cs) == -1)
|
|
ACELIB_ERROR ((LM_ERROR,
|
|
ACE_TEXT ("%p\n"),
|
|
ACE_TEXT ("ACE_Oneshot_Acceptor::ACE_Oneshot_Acceptor")));
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR>
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::~ACE_Oneshot_Acceptor (void)
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::~ACE_Oneshot_Acceptor");
|
|
this->handle_close ();
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::close (void)
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::close");
|
|
return this->handle_close ();
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::handle_close (ACE_HANDLE,
|
|
ACE_Reactor_Mask)
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::handle_close");
|
|
|
|
// Guard against multiple closes.
|
|
if (this->delete_concurrency_strategy_)
|
|
{
|
|
delete this->concurrency_strategy_;
|
|
this->delete_concurrency_strategy_ = false;
|
|
this->concurrency_strategy_ = 0;
|
|
}
|
|
// Note that if we aren't actually registered with the
|
|
// ACE_Reactor then it's ok for this call to fail...
|
|
|
|
if (this->reactor ())
|
|
this->reactor ()->remove_handler
|
|
(this,
|
|
ACE_Event_Handler::ACCEPT_MASK | ACE_Event_Handler::DONT_CALL);
|
|
|
|
if (this->peer_acceptor_.close () == -1)
|
|
ACELIB_ERROR ((LM_ERROR,
|
|
ACE_TEXT ("close\n")));
|
|
return 0;
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::handle_timeout
|
|
(const ACE_Time_Value &tv,
|
|
const void *arg)
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::handle_timeout");
|
|
errno = ETIME;
|
|
|
|
if (this->svc_handler_->handle_timeout (tv, arg) == -1)
|
|
this->svc_handler_->handle_close (this->svc_handler_->get_handle (),
|
|
ACE_Event_Handler::TIMER_MASK);
|
|
|
|
// Since we aren't necessarily registered with the Reactor, don't
|
|
// bother to check the return value here...
|
|
if (this->reactor ())
|
|
this->reactor ()->remove_handler (this,
|
|
ACE_Event_Handler::ACCEPT_MASK);
|
|
return 0;
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::cancel (void)
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::cancel");
|
|
return this->reactor () && this->reactor ()->cancel_timer (this);
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::register_handler
|
|
(SVC_HANDLER *svc_handler,
|
|
const ACE_Synch_Options &synch_options,
|
|
bool restart)
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::register_handler");
|
|
// Can't do this if we don't have a Reactor.
|
|
if (this->reactor () == 0)
|
|
{
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
this->svc_handler_ = svc_handler;
|
|
this->restart_ = restart;
|
|
ACE_Time_Value *tv = (ACE_Time_Value *) synch_options.time_value ();
|
|
|
|
if (tv != 0
|
|
&& this->reactor ()->schedule_timer (this,
|
|
synch_options.arg (),
|
|
*tv) == -1)
|
|
return -1;
|
|
else
|
|
return this->reactor ()->register_handler
|
|
(this,
|
|
ACE_Event_Handler::ACCEPT_MASK);
|
|
}
|
|
}
|
|
|
|
// 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).
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::activate_svc_handler
|
|
(SVC_HANDLER *svc_handler)
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::activate_svc_handler");
|
|
return this->concurrency_strategy_->activate_svc_handler
|
|
(svc_handler,
|
|
(void *) this);
|
|
}
|
|
|
|
// Factors out the code shared between the <accept> and <handle_input>
|
|
// methods.
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::shared_accept
|
|
(SVC_HANDLER *svc_handler,
|
|
typename PEER_ACCEPTOR::PEER_ADDR *remote_addr,
|
|
ACE_Time_Value *timeout,
|
|
bool restart,
|
|
bool reset_new_handle)
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::shared_accept");
|
|
if (svc_handler == 0)
|
|
return -1;
|
|
|
|
// Accept connection into the Svc_Handler.
|
|
else if (this->peer_acceptor_.accept (svc_handler->peer (), // stream
|
|
remote_addr, // remote address
|
|
timeout, // timeout
|
|
restart, // restart
|
|
reset_new_handle // reset new handle
|
|
) == -1)
|
|
{
|
|
// Check whether we just timed out or whether we failed...
|
|
if (!(errno == EWOULDBLOCK || errno == ETIME))
|
|
// Close down handler to avoid memory leaks.
|
|
svc_handler->close (CLOSE_DURING_NEW_CONNECTION);
|
|
return -1;
|
|
}
|
|
// Activate the <svc_handler> using the designated concurrency
|
|
// strategy (note that this method becomes responsible for handling
|
|
// errors and freeing up the memory if things go awry...)
|
|
else
|
|
return this->activate_svc_handler (svc_handler);
|
|
}
|
|
|
|
// Make a SVC_HANDLER, accept the connection into the SVC_HANDLER, and
|
|
// then activate the SVC_HANDLER. Note that SVC_HANDLER::open()
|
|
// decides what type of concurrency strategy to use.
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::accept
|
|
(SVC_HANDLER *svc_handler,
|
|
typename PEER_ACCEPTOR::PEER_ADDR *remote_addr,
|
|
const ACE_Synch_Options &synch_options,
|
|
bool restart,
|
|
bool reset_new_handle)
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::accept");
|
|
// Note that if timeout == ACE_Time_Value (x, y) where (x > 0 || y >
|
|
// 0) then this->connector_.connect() will block synchronously. If
|
|
// <use_reactor> is set then we don't want this to happen (since we
|
|
// want the ACE_Reactor to do the timeout asynchronously).
|
|
// Therefore, we'll force this->connector_ to use ACE_Time_Value (0,
|
|
// 0) in this case...
|
|
|
|
ACE_Time_Value *timeout;
|
|
int use_reactor = synch_options[ACE_Synch_Options::USE_REACTOR];
|
|
|
|
if (use_reactor)
|
|
timeout = (ACE_Time_Value *) &ACE_Time_Value::zero;
|
|
else
|
|
timeout = (ACE_Time_Value *) synch_options.time_value ();
|
|
|
|
if (this->shared_accept (svc_handler, // stream
|
|
remote_addr, // remote address
|
|
timeout, // timeout
|
|
restart, // restart
|
|
reset_new_handle // reset new handler
|
|
) == -1)
|
|
{
|
|
if (use_reactor && errno == EWOULDBLOCK)
|
|
// We couldn't accept right away, so let's wait in the
|
|
// <ACE_Reactor>.
|
|
this->register_handler (svc_handler,
|
|
synch_options,
|
|
restart);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Accepts one pending connection from a client (since we're the
|
|
// "oneshot" Acceptor).
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::handle_input (ACE_HANDLE)
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::handle_input");
|
|
int result = 0;
|
|
|
|
// Cancel any timer that might be pending.
|
|
this->cancel ();
|
|
|
|
// Try to find out if the implementation of the reactor that we are
|
|
// using requires us to reset the event association for the newly
|
|
// created handle. This is because the newly created handle will
|
|
// inherit the properties of the listen handle, including its event
|
|
// associations.
|
|
ACE_Reactor *reactor = this->reactor ();
|
|
bool reset_new_handle = false;
|
|
|
|
// There is a use-case whereby this object will be gone upon return
|
|
// from shared_accept - if the Svc_Handler deletes this Oneshot_Acceptor
|
|
// during the shared_accept/activation steps. So, do whatever we need
|
|
// to do with this object before calling shared_accept.
|
|
if (reactor)
|
|
{
|
|
reset_new_handle = reactor->uses_event_associations ();
|
|
reactor->remove_handler
|
|
(this,
|
|
ACE_Event_Handler::ACCEPT_MASK | ACE_Event_Handler::DONT_CALL);
|
|
}
|
|
|
|
if (this->shared_accept (this->svc_handler_, // stream
|
|
0, // remote address
|
|
0, // timeout
|
|
this->restart_, // restart
|
|
reset_new_handle // reset new handle
|
|
) == -1)
|
|
result = -1;
|
|
|
|
return result;
|
|
}
|
|
|
|
// Hook called by the explicit dynamic linking facility.
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::init (int, ACE_TCHAR *[])
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::init");
|
|
return -1;
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::fini (void)
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::fini");
|
|
return this->handle_close ();
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::info (ACE_TCHAR **strp,
|
|
size_t length) const
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::info");
|
|
ACE_TCHAR buf[BUFSIZ];
|
|
ACE_TCHAR addr_str[BUFSIZ];
|
|
typename PEER_ACCEPTOR::PEER_ADDR addr;
|
|
|
|
if (this->peer_acceptor_.get_local_addr (addr) == -1)
|
|
return -1;
|
|
else if (addr.addr_to_string (addr_str, sizeof addr_str) == -1)
|
|
return -1;
|
|
|
|
ACE_OS::sprintf (buf,
|
|
ACE_TEXT ("%s\t %s %s"),
|
|
ACE_TEXT ("ACE_Oneshot_Acceptor"),
|
|
addr_str,
|
|
ACE_TEXT ("#oneshot acceptor factory\n"));
|
|
|
|
if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
|
|
return -1;
|
|
else
|
|
ACE_OS::strsncpy (*strp, buf, length);
|
|
return static_cast<int> (ACE_OS::strlen (buf));
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::suspend (void)
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::suspend");
|
|
return this->reactor () && this->reactor ()->suspend_handler (this);
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> int
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::resume (void)
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::resume");
|
|
return this->reactor () && this->reactor ()->resume_handler (this);
|
|
}
|
|
|
|
// Returns ACE_HANDLE of the underlying peer_acceptor.
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> ACE_HANDLE
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::get_handle (void) const
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::get_handle");
|
|
return this->peer_acceptor_.get_handle ();
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR> PEER_ACCEPTOR &
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::acceptor (void) const
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::acceptor");
|
|
return (PEER_ACCEPTOR &) this->peer_acceptor_;
|
|
}
|
|
|
|
template <typename SVC_HANDLER, typename PEER_ACCEPTOR>
|
|
ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::operator PEER_ACCEPTOR & () const
|
|
{
|
|
ACE_TRACE ("ACE_Oneshot_Acceptor<SVC_HANDLER, PEER_ACCEPTOR>::operator PEER_ACCEPTOR &");
|
|
return (PEER_ACCEPTOR &) this->peer_acceptor_;
|
|
}
|
|
|
|
ACE_END_VERSIONED_NAMESPACE_DECL
|
|
|
|
#endif /* ACE_ACCEPTOR_CPP */
|