// Acceptor.cpp // $Id$ #ifndef ACE_ACCEPTOR_C #define ACE_ACCEPTOR_C #define ACE_BUILD_DLL #include "ace/ACE.h" #if !defined (ACE_LACKS_PRAGMA_ONCE) # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "ace/Acceptor.h" #include "ace/Handle_Set.h" #include "ace/WFMO_Reactor.h" ACE_RCSID(ace, Acceptor, "$Id$") ACE_ALLOC_HOOK_DEFINE(ACE_Acceptor) template void ACE_Acceptor::dump (void) const { ACE_TRACE ("ACE_Acceptor::dump"); ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); this->peer_acceptor_.dump (); ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); } template ACE_Acceptor::operator ACE_PEER_ACCEPTOR & () const { ACE_TRACE ("ACE_Acceptor::operator ACE_PEER_ACCEPTOR &"); return (ACE_PEER_ACCEPTOR &) this->peer_acceptor_; } template ACE_PEER_ACCEPTOR & ACE_Acceptor::acceptor (void) const { ACE_TRACE ("ACE_Acceptor::acceptor"); return (ACE_PEER_ACCEPTOR &) this->peer_acceptor_; } // Returns ACE_HANDLE of the underlying Acceptor_Strategy. template ACE_HANDLE ACE_Acceptor::get_handle (void) const { ACE_TRACE ("ACE_Acceptor::get_handle"); return this->peer_acceptor_.get_handle (); } // Initialize the appropriate strategies for creation, passive // connection acceptance, and concurrency, and then register // with the Reactor and listen for connection requests at the // designated . template int ACE_Acceptor::open (const ACE_PEER_ACCEPTOR_ADDR &local_addr, ACE_Reactor *reactor, int flags, int use_select, int reuse_addr) { ACE_TRACE ("ACE_Acceptor::open"); this->flags_ = flags; this->use_select_ = use_select; // Must supply a valid Reactor to Acceptor::open()... if (reactor == 0) { errno = EINVAL; return -1; } if (this->peer_acceptor_.open (local_addr, reuse_addr) == -1) return -1; int result = reactor->register_handler (this, ACE_Event_Handler::ACCEPT_MASK); if (result != -1) this->reactor (reactor); return result; } // Simple constructor. template ACE_Acceptor::ACE_Acceptor (ACE_Reactor *reactor, int use_select) : use_select_ (use_select) { ACE_TRACE ("ACE_Acceptor::ACE_Acceptor"); this->reactor (reactor); } template ACE_Acceptor::ACE_Acceptor (const ACE_PEER_ACCEPTOR_ADDR &addr, ACE_Reactor *reactor, int flags, int use_select, int reuse_addr) { ACE_TRACE ("ACE_Acceptor::ACE_Acceptor"); if (this->open (addr, reactor, flags, use_select, reuse_addr) == -1) ACE_ERROR ((LM_ERROR, ASYS_TEXT ("%p\n"), ASYS_TEXT ("ACE_Acceptor::ACE_Acceptor"))); } template ACE_Acceptor::~ACE_Acceptor (void) { ACE_TRACE ("ACE_Acceptor::~ACE_Acceptor"); this->handle_close (); } template int ACE_Acceptor::fini (void) { ACE_TRACE ("ACE_Acceptor::fini"); return ACE_Acceptor::handle_close (); } // Hook called by the explicit dynamic linking facility. template int ACE_Acceptor::init (int, ASYS_TCHAR *[]) { ACE_TRACE ("ACE_Acceptor::init"); return -1; } template int ACE_Acceptor::info (ASYS_TCHAR **strp, size_t length) const { ACE_TRACE ("ACE_Acceptor::info"); ASYS_TCHAR buf[BUFSIZ]; ASYS_TCHAR addr_str[BUFSIZ]; ACE_PEER_ACCEPTOR_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, ASYS_TEXT ("%s\t %s %s"), ASYS_TEXT ("ACE_Acceptor"), addr_str, ASYS_TEXT ("# acceptor factory\n")); if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0) return -1; else ACE_OS::strncpy (*strp, buf, length); return ACE_OS::strlen (buf); } template int ACE_Acceptor::suspend (void) { ACE_TRACE ("ACE_Acceptor::suspend"); return this->reactor ()->suspend_handler (this); } template int ACE_Acceptor::resume (void) { ACE_TRACE ("ACE_Acceptor::resume"); return this->reactor ()->resume_handler (this); } // Perform termination activities when is removed from the // . template int ACE_Acceptor::close (void) { ACE_TRACE ("ACE_Acceptor::close"); return this->handle_close (); } template int ACE_Acceptor::handle_close (ACE_HANDLE, ACE_Reactor_Mask) { ACE_TRACE ("ACE_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) ACE_ERROR ((LM_ERROR, ASYS_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 // . 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 int ACE_Acceptor::make_svc_handler (SVC_HANDLER *&sh) { ACE_TRACE ("ACE_Acceptor::make_svc_handler"); if (sh == 0) ACE_NEW_RETURN (sh, SVC_HANDLER, -1); return 0; } // Bridge method for accepting the new connection into the // . The default behavior delegates to the // PEER_ACCEPTOR::accept() in the Acceptor_Strategy. template int ACE_Acceptor::accept_svc_handler (SVC_HANDLER *svc_handler) { ACE_TRACE ("ACE_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. int reset_new_handle = this->reactor ()->uses_event_associations (); if (this->peer_acceptor_.accept (svc_handler->peer (), // stream 0, // remote address 0, // timeout 1, // restart reset_new_handle // reset new handler ) == -1) { // Close down handler to avoid memory leaks. svc_handler->close (0); return -1; } else return 0; } // Bridge method for activating a 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 int ACE_Acceptor::activate_svc_handler (SVC_HANDLER *svc_handler) { ACE_TRACE ("ACE_Acceptor::activate_svc_handler"); int result = 0; // See if we should enable non-blocking I/O on the '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) svc_handler->close (0); 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 int ACE_Acceptor::handle_input (ACE_HANDLE listener) { ACE_TRACE ("ACE_Acceptor::handle_input"); ACE_Handle_Set conn_handle; // 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*...). // @@ What should we do if any of the substrategies fail? Right // now, we just log an error message 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) ACE_ERROR_RETURN ((LM_ERROR, ASYS_TEXT ("%p\n"), ASYS_TEXT ("make_svc_handler")), 0); // Accept connection into the Svc_Handler. else if (this->accept_svc_handler (svc_handler) == -1) ACE_ERROR_RETURN ((LM_ERROR, ASYS_TEXT ("%p\n"), ASYS_TEXT ("accept_svc_handler")), 0); // Activate the 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) ACE_ERROR_RETURN ((LM_ERROR, ASYS_TEXT ("%p\n"), ASYS_TEXT ("activate_svc_handler")), 0); conn_handle.set_bit (listener); } // 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_OS::select (int (listener) + 1, conn_handle, 0, 0, &timeout) == 1); return 0; } ACE_ALLOC_HOOK_DEFINE(ACE_Strategy_Acceptor) template int ACE_Strategy_Acceptor::suspend (void) { ACE_TRACE ("ACE_Strategy_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::suspend (); } template int ACE_Strategy_Acceptor::resume (void) { ACE_TRACE ("ACE_Strategy_Acceptor::resume"); // First resume ourselves. if (ACE_Acceptor::resume () == -1) return -1; else // Then resume the SVC_HANDLER's we've created. return this->scheduling_strategy_->resume (); } template void ACE_Strategy_Acceptor::dump (void) const { ACE_TRACE ("ACE_Strategy_Acceptor::dump"); ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); ACE_Acceptor::dump (); this->creation_strategy_->dump (); ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("delete_creation_strategy_ = %d"), delete_creation_strategy_)); this->accept_strategy_->dump (); ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("delete_accept_strategy_ = %d"), delete_accept_strategy_)); this->concurrency_strategy_->dump (); ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("delete_concurrency_strategy_ = %d"), delete_concurrency_strategy_)); this->scheduling_strategy_->dump (); ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("delete_scheduling_strategy_ = %d"), delete_scheduling_strategy_)); ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("\nservice_name_ = %s"), this->service_name_)); ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("\nservice_description_ = %s"), this->service_description_)); ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("\nservice_port_ = %d"), this->service_port_)); this->service_addr_.dump (); ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); } template ACE_PEER_ACCEPTOR & ACE_Strategy_Acceptor::acceptor (void) const { ACE_TRACE ("ACE_Strategy_Acceptor::acceptor"); return this->accept_strategy_->acceptor (); } template ACE_Strategy_Acceptor::operator ACE_PEER_ACCEPTOR & () const { ACE_TRACE ("ACE_Strategy_Acceptor::operator ACE_PEER_ACCEPTOR &"); return this->accept_strategy_->acceptor (); } // Returns ACE_HANDLE of the underlying Acceptor_Strategy. template ACE_HANDLE ACE_Strategy_Acceptor::get_handle (void) const { ACE_TRACE ("ACE_Strategy_Acceptor::get_handle"); return this->accept_strategy_->get_handle (); } // Initialize the appropriate strategies for creation, passive // connection acceptance, and concurrency, and then register // with the Reactor and listen for connection requests at the // designated . template int ACE_Strategy_Acceptor::open (const ACE_PEER_ACCEPTOR_ADDR &local_addr, ACE_Reactor *reactor, ACE_Creation_Strategy *cre_s, ACE_Accept_Strategy *acc_s, ACE_Concurrency_Strategy *con_s, ACE_Scheduling_Strategy *sch_s, const ASYS_TCHAR *service_name, const ASYS_TCHAR *service_description, int use_select) { ACE_TRACE ("ACE_Strategy_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_ = 1; } 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_ = 1; } this->accept_strategy_ = acc_s; if (this->accept_strategy_->open (local_addr, 1) == -1) return -1; // Initialize the concurrency strategy. if (con_s == 0) { ACE_NEW_RETURN (con_s, CONCURRENCY_STRATEGY, -1); this->delete_concurrency_strategy_ = 1; } 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_ = 1; } this->scheduling_strategy_ = sch_s; this->use_select_ = use_select; return this->reactor ()->register_handler (this, ACE_Event_Handler::ACCEPT_MASK); } // Simple constructor. template ACE_Strategy_Acceptor::ACE_Strategy_Acceptor (const ASYS_TCHAR service_name[], const ASYS_TCHAR service_description[], int use_select) : creation_strategy_ (0), delete_creation_strategy_ (0), accept_strategy_ (0), delete_accept_strategy_ (0), concurrency_strategy_ (0), delete_concurrency_strategy_ (0), scheduling_strategy_ (0), delete_scheduling_strategy_ (0), service_name_ (0), service_description_ (0) { ACE_TRACE ("ACE_Strategy_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; } template ACE_Strategy_Acceptor::ACE_Strategy_Acceptor (const ACE_PEER_ACCEPTOR_ADDR &addr, ACE_Reactor *reactor, ACE_Creation_Strategy *cre_s, ACE_Accept_Strategy *acc_s, ACE_Concurrency_Strategy *con_s, ACE_Scheduling_Strategy *sch_s, const ASYS_TCHAR service_name[], const ASYS_TCHAR service_description[], int use_select) { ACE_TRACE ("ACE_Strategy_Acceptor::ACE_Strategy_Acceptor"); if (this->open (addr, reactor, cre_s, acc_s, con_s, sch_s, service_name, service_description, use_select) == -1) ACE_ERROR ((LM_ERROR, ASYS_TEXT ("%p\n"), ASYS_TEXT ("ACE_Strategy_Acceptor::ACE_Strategy_Acceptor"))); } // Perform termination activities when is removed from the // . template int ACE_Strategy_Acceptor::handle_close (ACE_HANDLE, ACE_Reactor_Mask) { ACE_TRACE ("ACE_Strategy_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_ = 0; this->creation_strategy_ = 0; if (this->delete_accept_strategy_) delete this->accept_strategy_; this->delete_accept_strategy_ = 0; this->accept_strategy_ = 0; if (this->delete_concurrency_strategy_) delete this->concurrency_strategy_; this->delete_concurrency_strategy_ = 0; this->concurrency_strategy_ = 0; if (this->delete_scheduling_strategy_) delete this->scheduling_strategy_; this->delete_scheduling_strategy_ = 0; this->scheduling_strategy_ = 0; // We must use the 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 . The strategy for // creating a are configured into the Acceptor via it's // . The default is to create a new // . However, subclasses can override this strategy to // perform creation in any way that they like (such as // creating subclass instances of , using a singleton, // dynamically linking the handler, etc.). template int ACE_Strategy_Acceptor::make_svc_handler (SVC_HANDLER *&sh) { ACE_TRACE ("ACE_Strategy_Acceptor::make_svc_handler"); return this->creation_strategy_->make_svc_handler (sh); } // Bridge method for accepting the new connection into the // . The default behavior delegates to the // in the Acceptor_Strategy. template int ACE_Strategy_Acceptor::accept_svc_handler (SVC_HANDLER *svc_handler) { ACE_TRACE ("ACE_Strategy_Acceptor::accept_svc_handler"); return this->accept_strategy_->accept_svc_handler (svc_handler); } // Bridge method for activating a 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 int ACE_Strategy_Acceptor::activate_svc_handler (SVC_HANDLER *svc_handler) { ACE_TRACE ("ACE_Strategy_Acceptor::activate_svc_handler"); return this->concurrency_strategy_->activate_svc_handler (svc_handler, (void *) this); } template ACE_Strategy_Acceptor::~ACE_Strategy_Acceptor (void) { ACE_TRACE ("ACE_Strategy_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 int ACE_Strategy_Acceptor::handle_signal (int, siginfo_t *, ucontext_t *) { ACE_Reactor::end_event_loop (); return 0; } template int ACE_Strategy_Acceptor::info (ASYS_TCHAR **strp, size_t length) const { ACE_TRACE ("ACE_Strategy_Acceptor::info"); ASYS_TCHAR buf[BUFSIZ]; ASYS_TCHAR service_addr_str[BUFSIZ]; ACE_PEER_ACCEPTOR_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, ASYS_TEXT ("%s\t %s #%s\n"), this->service_name_, service_addr_str, this->service_description_); if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0) return -1; else ACE_OS::strncpy (*strp, buf, length); return ACE_OS::strlen (buf); } template int ACE_Strategy_Acceptor::fini (void) { ACE_TRACE ("ACE_Strategy_Acceptor::fini"); return this->ACE_Strategy_Acceptor::handle_close (); } ACE_ALLOC_HOOK_DEFINE(ACE_Oneshot_Acceptor) template void ACE_Oneshot_Acceptor::dump (void) const { ACE_TRACE ("ACE_Oneshot_Acceptor::dump"); ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("\nsvc_handler_ = %x"), this->svc_handler_)); ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("\nrestart_ = %d"), this->restart_)); this->peer_acceptor_.dump (); ACE_DEBUG ((LM_DEBUG, ASYS_TEXT ("delete_concurrency_strategy_ = %d"), delete_concurrency_strategy_)); this->concurrency_strategy_->dump (); ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); } template int ACE_Oneshot_Acceptor::open (const ACE_PEER_ACCEPTOR_ADDR &local_addr, ACE_Reactor *reactor, ACE_Concurrency_Strategy *con_s) { ACE_TRACE ("ACE_Oneshot_Acceptor::open"); this->reactor (reactor); // Initialize the concurrency strategy. if (con_s == 0) { ACE_NEW_RETURN (con_s, ACE_Concurrency_Strategy, -1); this->delete_concurrency_strategy_ = 1; } this->concurrency_strategy_ = con_s; // Reuse the addr, even if it is already in use...! return this->peer_acceptor_.open (local_addr, 1); } template ACE_Oneshot_Acceptor::ACE_Oneshot_Acceptor (void) : delete_concurrency_strategy_ (0) { ACE_TRACE ("ACE_Oneshot_Acceptor::ACE_Oneshot_Acceptor"); this->reactor (0); } template ACE_Oneshot_Acceptor::ACE_Oneshot_Acceptor (const ACE_PEER_ACCEPTOR_ADDR &local_addr, ACE_Reactor *reactor, ACE_Concurrency_Strategy *cs) : delete_concurrency_strategy_ (0) { ACE_TRACE ("ACE_Oneshot_Acceptor::ACE_Oneshot_Acceptor"); if (this->open (local_addr, reactor, cs) == -1) ACE_ERROR ((LM_ERROR, ASYS_TEXT ("%p\n"), ASYS_TEXT ("ACE_Oneshot_Acceptor::ACE_Oneshot_Acceptor"))); } template ACE_Oneshot_Acceptor::~ACE_Oneshot_Acceptor (void) { ACE_TRACE ("ACE_Oneshot_Acceptor::~ACE_Oneshot_Acceptor"); this->handle_close (); } template int ACE_Oneshot_Acceptor::close (void) { ACE_TRACE ("ACE_Oneshot_Acceptor::close"); return this->handle_close (); } template int ACE_Oneshot_Acceptor::handle_close (ACE_HANDLE, ACE_Reactor_Mask) { ACE_TRACE ("ACE_Oneshot_Acceptor::handle_close"); // Guard against multiple closes. if (this->concurrency_strategy_ != 0) { if (this->delete_concurrency_strategy_) delete this->concurrency_strategy_; this->delete_concurrency_strategy_ = 0; 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) ACE_ERROR ((LM_ERROR, ASYS_TEXT ("close\n"))); } return 0; } template int ACE_Oneshot_Acceptor::handle_timeout (const ACE_Time_Value &tv, const void *arg) { ACE_TRACE ("ACE_Oneshot_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 int ACE_Oneshot_Acceptor::cancel (void) { ACE_TRACE ("ACE_Oneshot_Acceptor::cancel"); return this->reactor () && this->reactor ()->cancel_timer (this); } template int ACE_Oneshot_Acceptor::register_handler (SVC_HANDLER *svc_handler, const ACE_Synch_Options &synch_options, int restart) { ACE_TRACE ("ACE_Oneshot_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) == 0) return -1; else return this->reactor ()->register_handler (this, ACE_Event_Handler::ACCEPT_MASK); } } // Bridge method for activating a 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 int ACE_Oneshot_Acceptor::activate_svc_handler (SVC_HANDLER *svc_handler) { ACE_TRACE ("ACE_Oneshot_Acceptor::activate_svc_handler"); return this->concurrency_strategy_->activate_svc_handler (svc_handler, (void *) this); } // Factors out the code shared between the and // methods. template int ACE_Oneshot_Acceptor::shared_accept (SVC_HANDLER *svc_handler, ACE_PEER_ACCEPTOR_ADDR *remote_addr, ACE_Time_Value *timeout, int restart, int reset_new_handle) { ACE_TRACE ("ACE_Oneshot_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 (0); return -1; } // Activate the 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 int ACE_Oneshot_Acceptor::accept (SVC_HANDLER *svc_handler, ACE_PEER_ACCEPTOR_ADDR *remote_addr, const ACE_Synch_Options &synch_options, int restart, int reset_new_handle) { ACE_TRACE ("ACE_Oneshot_Acceptor::accept"); // Note that if timeout == ACE_Time_Value (x, y) where (x > 0 || y > // 0) then this->connector_.connect() will block synchronously. If // 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 // . 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 int ACE_Oneshot_Acceptor::handle_input (ACE_HANDLE) { ACE_TRACE ("ACE_Oneshot_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. int reset_new_handle = this->reactor ()->uses_event_associations (); 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; if (this->reactor () && this->reactor ()->remove_handler (this, ACE_Event_Handler::ACCEPT_MASK | ACE_Event_Handler::DONT_CALL) == -1) result = -1; return result; } // Hook called by the explicit dynamic linking facility. template int ACE_Oneshot_Acceptor::init (int, ASYS_TCHAR *[]) { ACE_TRACE ("ACE_Oneshot_Acceptor::init"); return -1; } template int ACE_Oneshot_Acceptor::fini (void) { ACE_TRACE ("ACE_Oneshot_Acceptor::fini"); return this->handle_close (); } template int ACE_Oneshot_Acceptor::info (ASYS_TCHAR **strp, size_t length) const { ACE_TRACE ("ACE_Oneshot_Acceptor::info"); ASYS_TCHAR buf[BUFSIZ]; ASYS_TCHAR addr_str[BUFSIZ]; ACE_PEER_ACCEPTOR_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, ASYS_TEXT ("%s\t %s %s"), ASYS_TEXT ("ACE_Oneshot_Acceptor"), addr_str, ASYS_TEXT ("#oneshot acceptor factory\n")); if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0) return -1; else ACE_OS::strncpy (*strp, buf, length); return ACE_OS::strlen (buf); } template int ACE_Oneshot_Acceptor::suspend (void) { ACE_TRACE ("ACE_Oneshot_Acceptor::suspend"); return this->reactor () && this->reactor ()->suspend_handler (this); } template int ACE_Oneshot_Acceptor::resume (void) { ACE_TRACE ("ACE_Oneshot_Acceptor::resume"); return this->reactor () && this->reactor ()->resume_handler (this); } // Returns ACE_HANDLE of the underlying peer_acceptor. template ACE_HANDLE ACE_Oneshot_Acceptor::get_handle (void) const { ACE_TRACE ("ACE_Oneshot_Acceptor::get_handle"); return this->peer_acceptor_.get_handle (); } template ACE_PEER_ACCEPTOR & ACE_Oneshot_Acceptor::acceptor (void) const { ACE_TRACE ("ACE_Oneshot_Acceptor::acceptor"); return (ACE_PEER_ACCEPTOR &) this->peer_acceptor_; } template ACE_Oneshot_Acceptor::operator ACE_PEER_ACCEPTOR & () const { ACE_TRACE ("ACE_Oneshot_Acceptor::operator ACE_PEER_ACCEPTOR &"); return (ACE_PEER_ACCEPTOR &) this->peer_acceptor_; } #endif /* ACE_ACCEPTOR_C */