static ACE_THR_FUNC_RETURN start_clients (void *) { // Client thread function. ACE_INET_Addr addr (rendezvous); ACE_SSL_SOCK_Connector connect; for (size_t i = 0 ; i < cli_conn_no; i++) { ACE_SSL_SOCK_Stream stream; if (connect.connect (stream, addr) < 0) { ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%t) %p\n"), ACE_TEXT ("connect"))); continue; } Client_Handler *new_handler = 0; ACE_NEW_RETURN (new_handler, Client_Handler, (ACE_THR_FUNC_RETURN)-1); if (new_handler->open (stream.get_handle ()) != 0) { delete new_handler; stream.close (); } } return 0; }
static ACE_THR_FUNC_RETURN worker (void *) { ACE_OS::sleep (3); const ACE_TCHAR *msg = ACE_TEXT ("Message from Connection worker"); ACE_TCHAR buf [BUFSIZ]; buf[0] = ACE_OS::strlen (msg) + 1; ACE_OS::strcpy (&buf[1], msg); ACE_INET_Addr addr (rendezvous); ACE_DEBUG((LM_DEBUG, "(%t) Spawning %d client threads...\n", cli_thrno)); int grp = ACE_Thread_Manager::instance ()->spawn_n (cli_thrno, &cli_worker, buf); ACE_ASSERT (grp != -1); ACE_Thread_Manager::instance ()->wait_grp (grp); ACE_DEBUG ((LM_DEBUG, "(%t) Client threads done; shutting down...\n")); ACE_SSL_SOCK_Stream stream; ACE_SSL_SOCK_Connector connect; if (connect.connect (stream, addr) == -1) ACE_ERROR ((LM_ERROR, "(%t) %p Error while connecting\n", "connect")); const ACE_TCHAR *sbuf = ACE_TEXT ("\011shutdown"); ACE_DEBUG ((LM_DEBUG, "shutdown stream handle = %x\n", stream.get_handle ())); if (stream.send_n (sbuf, (ACE_OS::strlen (sbuf) + 1) * sizeof (ACE_TCHAR)) == -1) ACE_ERROR ((LM_ERROR, "(%t) %p\n", "send_n")); stream.close (); return 0; }
static ACE_THR_FUNC_RETURN cli_worker (void *arg) { // Client thread function. ACE_INET_Addr addr (rendezvous); ACE_SSL_SOCK_Stream stream; ACE_SSL_SOCK_Connector connect; ACE_Time_Value delay (0, req_delay); size_t len = * reinterpret_cast<ACE_TCHAR *> (arg); for (size_t i = 0 ; i < cli_conn_no; i++) { if (connect.connect (stream, addr) < 0) { ACE_ERROR ((LM_ERROR, "(%t) %p\n", "connect")); continue; } for (size_t j = 0; j < cli_req_no; j++) { ACE_DEBUG ((LM_DEBUG, "(%t) conn_worker handle 0x%x, req %d\n", stream.get_handle (), j+1)); if (stream.send_n (arg, (len + 1) * sizeof (ACE_TCHAR)) == -1) { ACE_ERROR ((LM_ERROR, "(%t) %p\n", "send_n")); continue; } ACE_OS::sleep (delay); } stream.close (); } return 0; }
int ACE_SSL_SOCK_Acceptor::shared_accept_finish (ACE_SSL_SOCK_Stream& new_stream, int in_blocking_mode, int reset_new_handle) const { ACE_TRACE ("ACE_SSL_SOCK_Acceptor::shared_accept_finish ()"); ACE_HANDLE new_handle = new_stream.get_handle (); // Check to see if we were originally in blocking mode, and if so, // set the <new_stream>'s handle and <this> handle to be in blocking // mode. if (in_blocking_mode) { // Save/restore errno. ACE_Errno_Guard error (errno); // Only disable ACE_NONBLOCK if we weren't in non-blocking mode // originally. ACE::clr_flags (this->get_handle (), ACE_NONBLOCK); ACE::clr_flags (new_handle, ACE_NONBLOCK); } #if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0) if (reset_new_handle) // Reset the event association inherited by the new handle. ::WSAEventSelect ((SOCKET) new_handle, 0, 0); #else ACE_UNUSED_ARG (reset_new_handle); #endif /* ACE_WIN32 */ if (new_handle == ACE_INVALID_HANDLE) return -1; return 0; }
int ACE_SSL_SOCK_Acceptor::ssl_accept (ACE_SSL_SOCK_Stream &new_stream, ACE_Time_Value *timeout) const { SSL *ssl = new_stream.ssl (); if (SSL_is_init_finished (ssl)) return 0; if (!SSL_in_accept_init (ssl)) ::SSL_set_accept_state (ssl); // Register an event handler to complete the non-blocking SSL // accept. A specialized event handler is necessary since since // the ACE Acceptor strategies are not designed for protocols // that require additional handshakes after the initial accept. ACE_SSL_Accept_Handler eh (new_stream); const ACE_Reactor_Mask reactor_mask = ACE_Event_Handler::READ_MASK | ACE_Event_Handler::WRITE_MASK; // In case a thread other than the one running the Reactor event // loop performs the passive SSL connection establishment, transfer // ownership of the Reactor to the current thread. Control will be // passed back to the previous owner when accepting or rejecting the // passive SSL connection. ACE_thread_t old_owner; if (this->reactor_->owner (ACE_Thread::self (), &old_owner) != 0) return -1; // Failed to transfer ownership! Should never happen! if (this->reactor_->register_handler ( new_stream.get_handle (), &eh, reactor_mask) == -1) return -1; // Have the Reactor complete the SSL passive connection. Run the // event loop until the passive connection is completed. Since // the Reactor is used, this isn't a busy wait. while (!SSL_is_init_finished (ssl)) { // Before blocking in the Reactor, do an SSL_accept() in case // OpenSSL buffered additional data sent within an SSL record // during session negotiation. The buffered data must be // handled prior to entering the Reactor event loop since the // Reactor may end up waiting indefinitely for data that has // already arrived. int status = ::SSL_accept (ssl); switch (::SSL_get_error (ssl, status)) { case SSL_ERROR_NONE: break; case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: // No data buffered by OpenSSL, so wait for data in the // Reactor. if (this->reactor_->handle_events (timeout) == -1 || new_stream.get_handle () == ACE_INVALID_HANDLE) { (void) this->reactor_->remove_handler (&eh, reactor_mask); (void) this->reactor_->owner (old_owner); return -1; } break; case SSL_ERROR_ZERO_RETURN: // The peer has notified us that it is shutting down via // the SSL "close_notify" message so we need to // shutdown, too. // // Removing the event handler from the Reactor causes the // SSL stream to be shutdown. (void) this->reactor_->remove_handler (&eh, reactor_mask); (void) this->reactor_->owner (old_owner); return -1; case SSL_ERROR_SYSCALL: // On some platforms (e.g. MS Windows) OpenSSL does not // store the last error in errno so explicitly do so. ACE_OS::set_errno_to_last_error (); default: ACE_SSL_Context::report_error (); (void) this->reactor_->remove_handler (&eh, reactor_mask); (void) this->reactor_->owner (old_owner); return -1; } } // SSL passive connection was completed. Deregister the event // handler from the Reactor, but don't close it. (void) this->reactor_->remove_handler (&eh, reactor_mask | ACE_Event_Handler::DONT_CALL); // Transfer control of the Reactor to the previous owner. return this->reactor_->owner (old_owner); }
int ACE_SSL_SOCK_Acceptor::ssl_accept (ACE_SSL_SOCK_Stream &new_stream, ACE_Time_Value *timeout) const { SSL *ssl = new_stream.ssl (); if (SSL_is_init_finished (ssl)) return 0; if (!SSL_in_accept_init (ssl)) ::SSL_set_accept_state (ssl); ACE_HANDLE handle = new_stream.get_handle (); // We're going to call SSL_accept, optionally doing ACE::select and // retrying the SSL_accept, until the SSL handshake is done or // it fails. // To get the timeout affect, set the socket to nonblocking mode // before beginning if there is a timeout specified. If the timeout // is 0 (wait as long as it takes) then don't worry about the blocking // status; we'll block in SSL_accept if the socket is blocking, and // block in ACE::select if not. int reset_blocking_mode = 0; if (timeout != 0) { reset_blocking_mode = ACE_BIT_DISABLED (ACE::get_flags (handle), ACE_NONBLOCK); // Set the handle into non-blocking mode if it's not already // in it. if (reset_blocking_mode && ACE::set_flags (handle, ACE_NONBLOCK) == -1) return -1; } // Take into account the time between each select() call below. ACE_Countdown_Time countdown (timeout); int status; do { // These handle sets are used to set up for whatever SSL_accept // says it wants next. They're reset on each pass around the loop. ACE_Handle_Set rd_handle; ACE_Handle_Set wr_handle; status = ::SSL_accept (ssl); switch (::SSL_get_error (ssl, status)) { case SSL_ERROR_NONE: status = 0; // To tell caller about success break; // Done case SSL_ERROR_WANT_WRITE: wr_handle.set_bit (handle); status = 1; // Wait for more activity break; case SSL_ERROR_WANT_READ: rd_handle.set_bit (handle); status = 1; // Wait for more activity break; case SSL_ERROR_ZERO_RETURN: // The peer has notified us that it is shutting down via // the SSL "close_notify" message so we need to // shutdown, too. status = -1; break; case SSL_ERROR_SYSCALL: // On some platforms (e.g. MS Windows) OpenSSL does not // store the last error in errno so explicitly do so. // // Explicitly check for EWOULDBLOCK since it doesn't get // converted to an SSL_ERROR_WANT_{READ,WRITE} on some // platforms. If SSL_accept failed outright, though, don't // bother checking more. This can happen if the socket gets // closed during the handshake. if (ACE_OS::set_errno_to_last_error () == EWOULDBLOCK && status == -1) { // Although the SSL_ERROR_WANT_READ/WRITE isn't getting // set correctly, the read/write state should be valid. // Use that to decide what to do. status = 1; // Wait for more activity if (SSL_want_write (ssl)) wr_handle.set_bit (handle); else if (SSL_want_read (ssl)) rd_handle.set_bit (handle); else status = -1; // Doesn't want anything - bail out } else status = -1; break; default: ACE_SSL_Context::report_error (); status = -1; break; } if (status == 1) { // Must have at least one handle to wait for at this point. ACE_ASSERT (rd_handle.num_set() == 1 || wr_handle.num_set () == 1); status = ACE::select (int (handle) + 1, &rd_handle, &wr_handle, 0, timeout); (void) countdown.update (); // 0 is timeout, so we're done. // -1 is error, so we're done. // Could be both handles set (same handle in both masks) so // set to 1. if (status >= 1) status = 1; else // Timeout or failure status = -1; } } while (status == 1 && !SSL_is_init_finished (ssl)); if (reset_blocking_mode) { ACE_Errno_Guard eguard (errno); ACE::clr_flags (handle, ACE_NONBLOCK); } return (status == -1 ? -1 : 0); }