diff options
author | William R. Otte <wotte@dre.vanderbilt.edu> | 2006-07-24 15:50:30 +0000 |
---|---|---|
committer | William R. Otte <wotte@dre.vanderbilt.edu> | 2006-07-24 15:50:30 +0000 |
commit | c44379cc7d9c7aa113989237ab0f56db12aa5219 (patch) | |
tree | 66a84b20d47f2269d8bdc6e0323f338763424d3a /ACE/examples/IPC_SAP/SSL_SAP | |
parent | 3aff90f4a822fcf5d902bbfbcc9fa931d6191a8c (diff) | |
download | ATCD-c44379cc7d9c7aa113989237ab0f56db12aa5219.tar.gz |
Repo restructuring
Diffstat (limited to 'ACE/examples/IPC_SAP/SSL_SAP')
-rw-r--r-- | ACE/examples/IPC_SAP/SSL_SAP/Makefile.am | 196 | ||||
-rw-r--r-- | ACE/examples/IPC_SAP/SSL_SAP/README | 17 | ||||
-rw-r--r-- | ACE/examples/IPC_SAP/SSL_SAP/SSL-client-simple.cpp | 377 | ||||
-rw-r--r-- | ACE/examples/IPC_SAP/SSL_SAP/SSL-client-simple.h | 98 | ||||
-rw-r--r-- | ACE/examples/IPC_SAP/SSL_SAP/SSL-client.cpp | 418 | ||||
-rw-r--r-- | ACE/examples/IPC_SAP/SSL_SAP/SSL-client.h | 111 | ||||
-rw-r--r-- | ACE/examples/IPC_SAP/SSL_SAP/SSL-server-fancy.cpp | 606 | ||||
-rw-r--r-- | ACE/examples/IPC_SAP/SSL_SAP/SSL-server-fancy.h | 44 | ||||
-rw-r--r-- | ACE/examples/IPC_SAP/SSL_SAP/SSL-server-poll.cpp | 212 | ||||
-rw-r--r-- | ACE/examples/IPC_SAP/SSL_SAP/SSL-server-simple.cpp | 366 | ||||
-rw-r--r-- | ACE/examples/IPC_SAP/SSL_SAP/SSL-server.cpp | 430 | ||||
-rw-r--r-- | ACE/examples/IPC_SAP/SSL_SAP/SSL_SAP.mpc | 44 | ||||
-rw-r--r-- | ACE/examples/IPC_SAP/SSL_SAP/dummy.pem | 15 | ||||
-rw-r--r-- | ACE/examples/IPC_SAP/SSL_SAP/key.pem | 15 | ||||
-rw-r--r-- | ACE/examples/IPC_SAP/SSL_SAP/local_data | 1 | ||||
-rwxr-xr-x | ACE/examples/IPC_SAP/SSL_SAP/summarize | 45 |
16 files changed, 2995 insertions, 0 deletions
diff --git a/ACE/examples/IPC_SAP/SSL_SAP/Makefile.am b/ACE/examples/IPC_SAP/SSL_SAP/Makefile.am new file mode 100644 index 00000000000..3df4d11db5b --- /dev/null +++ b/ACE/examples/IPC_SAP/SSL_SAP/Makefile.am @@ -0,0 +1,196 @@ +## Process this file with automake to create Makefile.in +## +## $Id$ +## +## This file was generated by MPC. Any changes made directly to +## this file will be lost the next time it is generated. +## +## MPC Command: +## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu + +ACE_BUILDDIR = $(top_builddir) +ACE_ROOT = $(top_srcdir) + +noinst_PROGRAMS = + +## Makefile.SSL_SAP_Client.am + +if BUILD_SSL +if !BUILD_ACE_FOR_TAO + +noinst_PROGRAMS += client + +client_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) \ + -DACE_HAS_SSL=1 \ + @ACE_TLS_CPPFLAGS@ + +client_SOURCES = \ + SSL-client.cpp \ + SSL-client.h + +client_LDFLAGS = \ + @ACE_TLS_LDFLAGS@ + +client_LDADD = \ + $(ACE_BUILDDIR)/ace/SSL/libACE_SSL.la \ + $(ACE_BUILDDIR)/ace/libACE.la \ + @ACE_TLS_LIBS@ + +endif !BUILD_ACE_FOR_TAO +endif BUILD_SSL + +## Makefile.SSL_SAP_Client_Simple.am + +if BUILD_SSL +if !BUILD_ACE_FOR_TAO + +noinst_PROGRAMS += client-simple + +client_simple_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) \ + -DACE_HAS_SSL=1 \ + @ACE_TLS_CPPFLAGS@ + +client_simple_SOURCES = \ + SSL-client-simple.cpp \ + SSL-client-simple.h + +client_simple_LDFLAGS = \ + @ACE_TLS_LDFLAGS@ + +client_simple_LDADD = \ + $(ACE_BUILDDIR)/ace/SSL/libACE_SSL.la \ + $(ACE_BUILDDIR)/ace/libACE.la \ + @ACE_TLS_LIBS@ + +endif !BUILD_ACE_FOR_TAO +endif BUILD_SSL + +## Makefile.SSL_SAP_Server.am + +if BUILD_SSL +if !BUILD_ACE_FOR_TAO + +noinst_PROGRAMS += server + +server_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) \ + -DACE_HAS_SSL=1 \ + @ACE_TLS_CPPFLAGS@ + +server_SOURCES = \ + SSL-server.cpp \ + SSL-client-simple.h \ + SSL-client.h \ + SSL-server-fancy.h + +server_LDFLAGS = \ + @ACE_TLS_LDFLAGS@ + +server_LDADD = \ + $(ACE_BUILDDIR)/ace/SSL/libACE_SSL.la \ + $(ACE_BUILDDIR)/ace/libACE.la \ + @ACE_TLS_LIBS@ + +endif !BUILD_ACE_FOR_TAO +endif BUILD_SSL + +## Makefile.SSL_SAP_Server_Fancy.am + +if BUILD_SSL +if !BUILD_ACE_FOR_TAO + +noinst_PROGRAMS += server-fancy + +server_fancy_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) \ + -DACE_HAS_SSL=1 \ + @ACE_TLS_CPPFLAGS@ + +server_fancy_SOURCES = \ + SSL-server-fancy.cpp \ + SSL-server-fancy.h + +server_fancy_LDFLAGS = \ + @ACE_TLS_LDFLAGS@ + +server_fancy_LDADD = \ + $(ACE_BUILDDIR)/ace/SSL/libACE_SSL.la \ + $(ACE_BUILDDIR)/ace/libACE.la \ + @ACE_TLS_LIBS@ + +endif !BUILD_ACE_FOR_TAO +endif BUILD_SSL + +## Makefile.SSL_SAP_Server_Poll.am + +if BUILD_SSL +if !BUILD_ACE_FOR_TAO + +noinst_PROGRAMS += server-poll + +server_poll_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) \ + -DACE_HAS_SSL=1 \ + @ACE_TLS_CPPFLAGS@ + +server_poll_SOURCES = \ + SSL-server-poll.cpp \ + SSL-client-simple.h \ + SSL-client.h \ + SSL-server-fancy.h + +server_poll_LDFLAGS = \ + @ACE_TLS_LDFLAGS@ + +server_poll_LDADD = \ + $(ACE_BUILDDIR)/ace/SSL/libACE_SSL.la \ + $(ACE_BUILDDIR)/ace/libACE.la \ + @ACE_TLS_LIBS@ + +endif !BUILD_ACE_FOR_TAO +endif BUILD_SSL + +## Makefile.SSL_SAP_Server_Simple.am + +if BUILD_SSL +if !BUILD_ACE_FOR_TAO + +noinst_PROGRAMS += server-simple + +server_simple_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) \ + -DACE_HAS_SSL=1 \ + @ACE_TLS_CPPFLAGS@ + +server_simple_SOURCES = \ + SSL-server-simple.cpp \ + SSL-client-simple.h \ + SSL-client.h \ + SSL-server-fancy.h + +server_simple_LDFLAGS = \ + @ACE_TLS_LDFLAGS@ + +server_simple_LDADD = \ + $(ACE_BUILDDIR)/ace/SSL/libACE_SSL.la \ + $(ACE_BUILDDIR)/ace/libACE.la \ + @ACE_TLS_LIBS@ + +endif !BUILD_ACE_FOR_TAO +endif BUILD_SSL + +## Clean up template repositories, etc. +clean-local: + -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.* + -rm -f gcctemp.c gcctemp so_locations *.ics + -rm -rf cxx_repository ptrepository ti_files + -rm -rf templateregistry ir.out + -rm -rf ptrepository SunWS_cache Templates.DB diff --git a/ACE/examples/IPC_SAP/SSL_SAP/README b/ACE/examples/IPC_SAP/SSL_SAP/README new file mode 100644 index 00000000000..43f4640e75a --- /dev/null +++ b/ACE/examples/IPC_SAP/SSL_SAP/README @@ -0,0 +1,17 @@ +# $Id$ + +This directory contains groups of client and server test programs that +exercise the various C++ wrappers for SSL sockets. In general, the +test programs do more or less the same thing -- the client establishes +a connection with the server and then transfers data to the server, +which keeps printing the data until EOF is reached (e.g., user types +^D). + +Unless noted differently, the server is implemented as an "iterative +server," i.e., it only deals with one client at a time. The following +describes each set of tests in more detail: + + . SSL-{client,server}.cpp -- This test allows you to test + oneway and twoway socket communication latency and + throughput over SSL between two processes on the same + machine or on different machines. diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL-client-simple.cpp b/ACE/examples/IPC_SAP/SSL_SAP/SSL-client-simple.cpp new file mode 100644 index 00000000000..31f76d4826a --- /dev/null +++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL-client-simple.cpp @@ -0,0 +1,377 @@ +// $Id$ + +// This tests the features of the <ACE_SSL_SOCK_Connector> and +// <ACE_SSL_SOCK_Stream> classes. In addition, it can be used to test the +// oneway and twoway latency and throughput at the socket-level. This +// is useful as a baseline to compare against ORB-level performance +// for the same types of data. + +#include "ace/OS_NS_string.h" +#include "ace/OS_NS_unistd.h" +#include "ace/INET_Addr.h" +#include "ace/Log_Msg.h" +#include "ace/Singleton.h" +#include "ace/Get_Opt.h" +#include "ace/High_Res_Timer.h" +#include "ace/Null_Mutex.h" + +#include "ace/SSL/SSL_SOCK_Connector.h" + +#include "SSL-client-simple.h" + +ACE_RCSID (SSL_SAP, + SSL_client_simple, + "$Id$") + + +Options::Options (void) + : host_ (ACE_DEFAULT_SERVER_HOST), + port_ (ACE_DEFAULT_SERVER_PORT), + sleep_time_ (0, 0), // By default, don't sleep between calls. + message_len_ (0), + message_buf_ (0), + io_source_ (ACE_INVALID_HANDLE), // Defaults to using the generator. + iterations_ (10000), + oneway_ (1) // Make oneway calls the default. +{ + ACE_OS::strcpy (quit_string_, "q"); +} + +Options::~Options (void) +{ + delete [] this->message_buf_; +} + +// Options Singleton. +typedef ACE_Singleton<Options, ACE_Null_Mutex> OPTIONS; + +int +Options::init (void) +{ + // Check for default case. + if (this->message_len_ == 0) + this->message_len_ = ACE_OS::strlen ("TAO"); + + this->message_len_ += sizeof (ACE_UINT32); + + ACE_NEW_RETURN (this->message_buf_, + char[this->message_len_], + -1); + + // Copy the length into the beginning of the message. + ACE_UINT32 length = ntohl (this->message_len_); + ACE_OS::memcpy ((void *) this->message_buf_, + (void *) &length, + sizeof length); + + ACE_OS::memset ((void *) (this->message_buf_ + sizeof (ACE_UINT32)), + 'a', + this->message_len_ - sizeof (ACE_UINT32)); + + return 0; +} + +size_t +Options::message_len (void) const +{ + return this->message_len_; +} + +const void * +Options::message_buf (void) const +{ + return this->message_buf_; +} + +ssize_t +Options::read (void *buf, size_t len, size_t &iteration) +{ + ACE_UNUSED_ARG (len); + + if (this->io_source_ == ACE_STDIN) + return ACE_OS::read (ACE_STDIN, buf, len); + else if (iteration >= this->iterations_) + return 0; + else + { + ACE_OS::memcpy (buf, + this->message_buf (), + len); + iteration++; + return len; + } +} + +int +Options::parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt getopt (argc, argv, ACE_TEXT ("2h:i:m:p:q:sT:"), 1); + + for (int c; (c = getopt ()) != -1; ) + switch (c) + { + case '2': // Disable the oneway client. + this->oneway_ = 0; + break; + case 'h': + this->host_ = getopt.opt_arg (); + break; + case 'i': + this->iterations_ = ACE_OS::atoi (getopt.opt_arg ()); + break; + case 'm': + this->message_len_ = ACE_OS::atoi (getopt.opt_arg ()); + break; + case 'p': + this->port_ = ACE_OS::atoi (getopt.opt_arg ()); + break; + case 'q': + ACE_OS::strncpy (this->quit_string_, + ACE_TEXT_ALWAYS_CHAR (getopt.opt_arg ()), + QUIT_STRING_SIZE); + break; + case 's': + this->io_source_ = ACE_STDIN; + break; + case 'T': + this->sleep_time_.set (0, ACE_OS::atoi (getopt.opt_arg ())); + break; + default: + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) usage: %n [-2] [-h <host>] ") + ACE_TEXT ("[-i iterations] [-m message-size] ") + ACE_TEXT ("[-p <port>] [-q <quit string>] ") + ACE_TEXT ("[-s] [-T <sleep_time>]\n")), + -1); + } + + return this->init (); +} + +u_short +Options::port (void) const +{ + return this->port_; +} + +const ACE_TCHAR * +Options::host (void) const +{ + return this->host_; +} + +const char * +Options::quit_string (void) const +{ + return this->quit_string_; +} + +const ACE_Time_Value & +Options::sleep_time (void) const +{ + return this->sleep_time_; +} + +char * +Options::shared_client_test (u_short port, + ACE_SSL_SOCK_Stream &cli_stream) +{ + ACE_INET_Addr remote_addr (port, this->host_); + + ACE_SSL_SOCK_Connector con; + + if (con.connect (cli_stream, + remote_addr) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n"), + ACE_TEXT ("connection failed")), + 0); + else + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) connected to %C at port %d\n"), + remote_addr.get_host_name (), + remote_addr.get_port_number ())); + + char *buf; + ACE_NEW_RETURN (buf, + char[this->message_len ()], + 0); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) waiting...\n"))); + + return buf; +} +// Static function entry point to the oneway client service. + +void +Options::oneway_client_test (void) +{ + ACE_SSL_SOCK_Stream cli_stream; + + // Add 1 to the port to trigger the oneway test! + char *request = this->shared_client_test (this->port () + 1, + cli_stream); + if (request == 0) + return; + + // This variable is allocated off the stack to obviate the need for + // locking. + size_t iteration = 0; + + // Keep track of return value. + int result = 0; + ACE_INT32 len = this->message_len (); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) starting oneway transmission\n"))); + + // Perform oneway transmission of data to server (correctly handles + // "incomplete writes"). + + for (ssize_t r_bytes; + (r_bytes = this->read (request, len, iteration)) > 0; + // Transmit at the proper rate. + ACE_OS::sleep (this->sleep_time ())) + if (ACE_OS::memcmp (request, + this->quit_string (), + ACE_OS::strlen (this->quit_string ())) == 0) + break; + else if (cli_stream.send_n (request, r_bytes) == -1) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n"), + ACE_TEXT ("send_n"))); + result = -1; + break; + } + + // Close the connection. + cli_stream.close (); + + delete [] request; +} + +// Static function entry point to the twoway client service. + +void +Options::twoway_client_test (void) +{ + ACE_SSL_SOCK_Stream cli_stream; + + char *request = this->shared_client_test (this->port (), + cli_stream); + if (request == 0) + return; + + // This variable is allocated off the stack to obviate the need for + // locking. + size_t iteration = 0; + + // Keep track of return value. + int result = 0; + + // Timer business. + ACE_High_Res_Timer timer; + + ACE_INT32 len = this->message_len (); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) starting twoway transmission\n"))); + + // Perform twoway transmission of data to server (correctly handles + // "incomplete writes"). + + for (ssize_t r_bytes; + (r_bytes = this->read (request, len, iteration)) > 0; + // Transmit at the proper rate. + ACE_OS::sleep (this->sleep_time ())) + if (ACE_OS::memcmp (request, + this->quit_string (), + ACE_OS::strlen (this->quit_string ())) == 0) + break; + + // Transmit <request> to the server. + else + { + // Note that we use the incremental feature of the + // <ACE_High_Res_Timer> so that we don't get "charged" for the + // <ACE_OS::sleep> used to control the rate at which requests + // are sent. + timer.start_incr (); + + if (cli_stream.send_n (request, r_bytes) == -1) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n"), + ACE_TEXT ("send_n"))); + result = -1; + break; + } + // Receive the reply from the server. Normally, it just sends + // back 24 bytes, which is typical for an IIOP reply. + else if (cli_stream.recv (request, r_bytes) <= 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n"), + ACE_TEXT ("recv"))); + result = -1; + break; + } + + timer.stop_incr (); + } + + ACE_Time_Value tv; + + timer.elapsed_time_incr (tv); + double real_time = tv.sec () * ACE_ONE_SECOND_IN_USECS + tv.usec (); + double messages_per_sec = iteration * double (ACE_ONE_SECOND_IN_USECS) / real_time; + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%t) messages = %d\n(%t) usec-per-message = %f\n(%t) messages-per-second = %0.00f\n"), + iteration, + real_time / double (iteration), + messages_per_sec < 0 ? 0 : messages_per_sec)); + + // Close the connection. + cli_stream.close (); + + delete [] request; +} + +void +Options::run (void) +{ + if (this->oneway_ == 0) + this->twoway_client_test (); + else + this->oneway_client_test (); +} + +static int +run_client (void) +{ + // Raise the socket handle limit to the maximum. + ACE::set_handle_limit (); + + OPTIONS::instance ()->run (); + + return 0; +} + +int +ACE_TMAIN (int argc, ACE_TCHAR *argv[]) +{ + // Initialize the logger. + ACE_LOG_MSG->open (argv[0]); + + if (OPTIONS::instance ()->parse_args (argc, argv) == -1) + return -1; + + // Run the client + run_client (); + + return 0; +} + diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL-client-simple.h b/ACE/examples/IPC_SAP/SSL_SAP/SSL-client-simple.h new file mode 100644 index 00000000000..4ec6b815a4c --- /dev/null +++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL-client-simple.h @@ -0,0 +1,98 @@ +// -*- C++ -*- +// $Id$ + +// This file defines the Options class for SSL-client-simple. IBM C++ +// compiler's template auto-instantiator needs this in a separate file. + +#ifndef ACE_SSL_CLIENT_SIMPLE_H +#define ACE_SSL_CLIENT_SIMPLE_H + +#include "ace/SSL/SSL_SOCK_Stream.h" +#include "ace/Time_Value.h" + +class Options + // = TITLE + // Define the options for this test. +{ +public: + Options (void); + // Constructor. + + ~Options (void); + // Destructor. + + int parse_args (int argc, ACE_TCHAR *argv[]); + // Parse the command-line arguments. + + const ACE_Time_Value &sleep_time (void) const; + // Return the amount of time to sleep in order to implement the + // proper transmission rates. + + u_short port (void) const; + // Port of the server. + + const ACE_TCHAR *host (void) const; + // Host of the server. + + const char *quit_string (void) const; + // String that shuts down the client/server. + + ssize_t read (void *buf, size_t len, size_t &iterations); + // Read from the appropriate location. + + size_t message_len (void) const; + // Returns the length of the message to send. + + const void *message_buf (void) const; + // Returns a pointer to the message. + + void run (void); + // Run the test + +private: + int init (void); + // Initialize the message we're sending to the user and set up the + // barrier. + + char *shared_client_test (u_short port, + ACE_SSL_SOCK_Stream &cli_stream); + // Performs the shared behavior of the oneway and twoway client + // tests. + + void twoway_client_test (void); + // Performs the twoway test. + + void oneway_client_test (void); + // Performs the oneway test. + + const ACE_TCHAR *host_; + // Host of the server. + + u_short port_; + // Port of the server. + + ACE_Time_Value sleep_time_; + // Sleep_Time value. + + enum {QUIT_STRING_SIZE = 128}; + char quit_string_[QUIT_STRING_SIZE]; + // String that shuts down the client/server. + + size_t message_len_; + // Size of the message we send to the server. + + char *message_buf_; + // Pointer to the message we send to the server. + + ACE_HANDLE io_source_; + // Are we reading I/O from ACE_STDIN or from our generator? + + size_t iterations_; + // Number of iterations. + + char oneway_; + // Are we running oneway or twoway? + +}; + +#endif /* ACE_SSL_CLIENT_SIMPLE_H */ diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL-client.cpp b/ACE/examples/IPC_SAP/SSL_SAP/SSL-client.cpp new file mode 100644 index 00000000000..539b97c931c --- /dev/null +++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL-client.cpp @@ -0,0 +1,418 @@ +// $Id$ + +// This tests the features of the <ACE_SSL_SOCK_Connector> and +// <ACE_SSL_SOCK_Stream> classes. In addition, it can be used to test the +// oneway and twoway latency and throughput at the socket-level. This +// is useful as a baseline to compare against ORB-level performance +// for the same types of data. + +#include "ace/OS_NS_string.h" +#include "ace/OS_NS_unistd.h" +#include "ace/INET_Addr.h" +#include "ace/Thread_Manager.h" +#include "ace/Singleton.h" +#include "ace/Get_Opt.h" +#include "ace/High_Res_Timer.h" + +#include "ace/SSL/SSL_SOCK_Connector.h" + +#include "SSL-client.h" + +ACE_RCSID(SSL_SAP, SSL_client, "$Id$") + +Options::Options (void) + : host_ (ACE_DEFAULT_SERVER_HOST), + port_ (ACE_DEFAULT_SERVER_PORT), + sleep_time_ (0, 0), // By default, don't sleep between calls. + threads_ (10), + message_len_ (0), + message_buf_ (0), + io_source_ (ACE_INVALID_HANDLE), // Defaults to using the generator. + iterations_ (10000), + oneway_ (1) // Make oneway calls the default. +#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) + , barrier_ (0) +#endif /* ACE_MT_SAFE */ +{ + ACE_OS::strcpy (quit_string_, "q"); +} + +Options::~Options (void) +{ + ACE_MT (delete this->barrier_); + delete [] this->message_buf_; +} + +// Options Singleton. +typedef ACE_Singleton<Options, ACE_SYNCH_RECURSIVE_MUTEX> OPTIONS; + +int +Options::init (void) +{ + // Check for default case. + if (this->message_len_ == 0) + this->message_len_ = ACE_OS::strlen ("TAO"); + + this->message_len_ += sizeof (ACE_UINT32); + + ACE_NEW_RETURN (this->message_buf_, + char[this->message_len_], + -1); + + // Copy the length into the beginning of the message. + ACE_UINT32 length = ntohl (this->message_len_); + ACE_OS::memcpy ((void *) this->message_buf_, + (void *) &length, + sizeof length); + + ACE_OS::memset ((void *) (this->message_buf_ + sizeof (ACE_UINT32)), + 'a', + this->message_len_ - sizeof (ACE_UINT32)); + + // Allocate the barrier with the correct count. + ACE_MT (ACE_NEW_RETURN (this->barrier_, + ACE_Barrier (this->threads_), + -1)); + return 0; +} + +size_t +Options::message_len (void) const +{ + return this->message_len_; +} + +const void * +Options::message_buf (void) const +{ + return this->message_buf_; +} + +ssize_t +Options::read (void *buf, size_t len, size_t &iteration) +{ + ACE_UNUSED_ARG (len); + + if (this->io_source_ == ACE_STDIN) + return ACE_OS::read (ACE_STDIN, buf, len); + else if (iteration >= this->iterations_) + return 0; + else + { + ACE_OS::memcpy (buf, + this->message_buf (), + len); + iteration++; + return len; + } +} + +int +Options::parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt getopt (argc, argv, ACE_TEXT ("2h:i:m:p:q:st:T:"), 1); + + for (int c; (c = getopt ()) != -1; ) + switch (c) + { + case '2': // Disable the oneway client. + this->oneway_ = 0; + break; + case 'h': + this->host_ = getopt.opt_arg (); + break; + case 'i': + this->iterations_ = ACE_OS::atoi (getopt.opt_arg ()); + break; + case 'm': + this->message_len_ = ACE_OS::atoi (getopt.opt_arg ()); + break; + case 'p': + this->port_ = ACE_OS::atoi (getopt.opt_arg ()); + break; + case 'q': + ACE_OS::strncpy (this->quit_string_, + ACE_TEXT_ALWAYS_CHAR (getopt.opt_arg ()), + QUIT_STRING_SIZE); + break; + case 's': + this->io_source_ = ACE_STDIN; + break; + case 't': + this->threads_ = (size_t) ACE_OS::atoi (getopt.opt_arg ()); + break; + case 'T': + this->sleep_time_.set (0, ACE_OS::atoi (getopt.opt_arg ())); + break; + default: + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) usage: %n [-2] [-h <host>] ") + ACE_TEXT ("[-i iterations] [-m message-size] ") + ACE_TEXT ("[-p <port>] [-q <quit string>] ") + ACE_TEXT ("[-s] [-t <threads>] [-T <sleep_time>]\n")), + -1); + } + + return this->init (); +} + +u_short +Options::port (void) const +{ + return this->port_; +} + +const ACE_TCHAR * +Options::host (void) const +{ + return this->host_; +} + +const char * +Options::quit_string (void) const +{ + return this->quit_string_; +} + +size_t +Options::threads (void) const +{ + return this->threads_; +} + +const ACE_Time_Value & +Options::sleep_time (void) const +{ + return this->sleep_time_; +} + +char * +Options::shared_client_test (u_short port, + ACE_SSL_SOCK_Stream &cli_stream) +{ + ACE_INET_Addr remote_addr (port, this->host_); + + ACE_SSL_SOCK_Connector con; + + if (con.connect (cli_stream, + remote_addr) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n"), + ACE_TEXT ("connection failed")), + 0); + else + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) connected to %C at port %d\n"), + remote_addr.get_host_name (), + remote_addr.get_port_number ())); + + // Allocate the transmit buffer. + char *buf; + ACE_NEW_RETURN (buf, + char[this->message_len ()], + 0); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) waiting...\n"))); + + // Wait for all other threads to finish initialization. + ACE_MT (this->barrier_->wait ()); + return buf; +} +// Static function entry point to the oneway client service. + +void * +Options::oneway_client_test (void *) +{ + Options *options = OPTIONS::instance (); + ACE_SSL_SOCK_Stream cli_stream; + + // Add 1 to the port to trigger the oneway test! + char *request = options->shared_client_test (options->port () + 1, + cli_stream); + if (request == 0) + return 0; + + // This variable is allocated off the stack to obviate the need for + // locking. + size_t iteration = 0; + + // Keep track of return value. + size_t result = 0; + ACE_INT32 len = options->message_len (); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) starting oneway transmission\n"))); + + // Perform oneway transmission of data to server (correctly handles + // "incomplete writes"). + + for (ssize_t r_bytes; + (r_bytes = options->read (request, len, iteration)) > 0; + // Transmit at the proper rate. + ACE_OS::sleep (options->sleep_time ())) + if (ACE_OS::memcmp (request, + options->quit_string (), + ACE_OS::strlen (options->quit_string ())) == 0) + break; + else if (cli_stream.send_n (request, r_bytes) == -1) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n"), + ACE_TEXT ("send_n"))); + result = size_t (-1); + break; + } + + // Close the connection. + cli_stream.close (); + + delete [] request; + return (void *) result; +} + +// Static function entry point to the twoway client service. + +void * +Options::twoway_client_test (void *) +{ + Options *options = OPTIONS::instance (); + + ACE_SSL_SOCK_Stream cli_stream; + + char *request = options->shared_client_test (options->port (), + cli_stream); + if (request == 0) + return 0; + + // This variable is allocated off the stack to obviate the need for + // locking. + size_t iteration = 0; + + // Keep track of return value. + size_t result = 0; + + // Timer business. + ACE_High_Res_Timer timer; + + ACE_INT32 len = options->message_len (); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) starting twoway transmission\n"))); + + // Perform twoway transmission of data to server (correctly handles + // "incomplete writes"). + + for (ssize_t r_bytes; + (r_bytes = options->read (request, len, iteration)) > 0; + // Transmit at the proper rate. + ACE_OS::sleep (options->sleep_time ())) + if (ACE_OS::memcmp (request, + options->quit_string (), + ACE_OS::strlen (options->quit_string ())) == 0) + break; + + // Transmit <request> to the server. + else + { + // Note that we use the incremental feature of the + // <ACE_High_Res_Timer> so that we don't get "charged" for the + // <ACE_OS::sleep> used to control the rate at which requests + // are sent. + timer.start_incr (); + + if (cli_stream.send_n (request, r_bytes) == -1) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n"), + ACE_TEXT ("send_n"))); + result = size_t (-1); + break; + } + // Receive the reply from the server. Normally, it just sends + // back 24 bytes, which is typical for an IIOP reply. + else if (cli_stream.recv (request, r_bytes) <= 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n"), + ACE_TEXT ("recv"))); + result = size_t (-1); + break; + } + + timer.stop_incr (); + } + + ACE_Time_Value tv; + + timer.elapsed_time_incr (tv); + double real_time = tv.sec () * ACE_ONE_SECOND_IN_USECS + tv.usec (); + double messages_per_sec = + iteration * double (ACE_ONE_SECOND_IN_USECS) / real_time; + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%t) messages = %d\n") + ACE_TEXT ("(%t) usec-per-message = %f\n") + ACE_TEXT ("(%t) messages-per-second = %0.00f\n"), + iteration, + real_time / double (iteration), + messages_per_sec < 0 ? 0 : messages_per_sec)); + + // Close the connection. + cli_stream.close (); + + delete [] request; + return (void *) result; +} + +ACE_THR_FUNC +Options::thr_func (void) +{ + if (this->oneway_ == 0) + return ACE_THR_FUNC (&Options::twoway_client_test); + else + return ACE_THR_FUNC (&Options::oneway_client_test); +} + +static int +run_client (void) +{ + // Raise the socket handle limit to the maximum. + ACE::set_handle_limit (); + +#if defined (ACE_HAS_THREADS) + if (ACE_Thread_Manager::instance ()->spawn_n ( + OPTIONS::instance ()->threads (), + OPTIONS::instance ()->thr_func ()) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n"), + ACE_TEXT ("spawn_n")), + 1); + else + ACE_Thread_Manager::instance ()->wait (); +#else + *(OPTIONS::instance ()->thr_func) (); +#endif /* ACE_HAS_THREADS */ + return 0; +} + +int +ACE_TMAIN (int argc, ACE_TCHAR *argv[]) +{ + ACE_SSL_Context *context = ACE_SSL_Context::instance (); + + context->certificate ("./dummy.pem", SSL_FILETYPE_PEM); + context->private_key ("./key.pem", SSL_FILETYPE_PEM); + + // Initialize the logger. + ACE_LOG_MSG->open (argv[0]); + + if (OPTIONS::instance ()->parse_args (argc, argv) == -1) + return -1; + + // Run the client + run_client (); + + return 0; +} + diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL-client.h b/ACE/examples/IPC_SAP/SSL_SAP/SSL-client.h new file mode 100644 index 00000000000..af081004368 --- /dev/null +++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL-client.h @@ -0,0 +1,111 @@ +// -*- C++ -*- +// $Id$ + +// This file defines the Options class for SSL-client. IBM C++ compiler'd +// template auto-instantiator needs this in a separate file. + +#ifndef __ACE_SSL_CLIENT_H +#define __ACE_SSL_CLIENT_H + +#include "ace/Barrier.h" +#include "ace/Time_Value.h" + +#include "ace/SSL/SSL_SOCK_Stream.h" + +class Options + // = TITLE + // Define the options for this test. +{ +public: + Options (void); + // Constructor. + + ~Options (void); + // Destructor. + + int parse_args (int argc, ACE_TCHAR *argv[]); + // Parse the command-line arguments. + + const ACE_Time_Value &sleep_time (void) const; + // Return the amount of time to sleep in order to implement the + // proper transmission rates. + + u_short port (void) const; + // Port of the server. + + const ACE_TCHAR *host (void) const; + // Host of the server. + + size_t threads (void) const; + // Number of threads. + + const char *quit_string (void) const; + // String that shuts down the client/server. + + ssize_t read (void *buf, size_t len, size_t &iterations); + // Read from the appropriate location. + + size_t message_len (void) const; + // Returns the length of the message to send. + + const void *message_buf (void) const; + // Returns a pointer to the message. + + ACE_THR_FUNC thr_func (void); + // Returns a pointer to the entry point into the thread that runs + // the client test function. + +private: + int init (void); + // Initialize the message we're sending to the user and set up the + // barrier. + + char *shared_client_test (u_short port, + ACE_SSL_SOCK_Stream &cli_stream); + // Performs the shared behavior of the oneway and twoway client + // tests. + + static void *twoway_client_test (void *); + // Performs the twoway test. + + static void *oneway_client_test (void *); + // Performs the oneway test. + + const ACE_TCHAR *host_; + // Host of the server. + + u_short port_; + // Port of the server. + + ACE_Time_Value sleep_time_; + // Sleep_Time value. + + size_t threads_; + // Number of threads. + + enum {QUIT_STRING_SIZE = 128}; + char quit_string_[QUIT_STRING_SIZE]; + // String that shuts down the client/server. + + size_t message_len_; + // Size of the message we send to the server. + + char *message_buf_; + // Pointer to the message we send to the server. + + ACE_HANDLE io_source_; + // Are we reading I/O from ACE_STDIN or from our generator? + + size_t iterations_; + // Number of iterations. + + char oneway_; + // Are we running oneway or twoway? + + // Please leave the ; inside the parenthesis to avoid Green Hills + // (and probably other) compiler warning about extra ;. + ACE_MT (ACE_Barrier *barrier_;) + // Barrier used to synchronize the start of all the threads. +}; + +#endif /* __ACE_SSL_CLIENT_H */ diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-fancy.cpp b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-fancy.cpp new file mode 100644 index 00000000000..e2d2c8ad0c1 --- /dev/null +++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-fancy.cpp @@ -0,0 +1,606 @@ +// $Id$ + +// This example tests the features of the <ACE_SSL_SOCK_Acceptor>, +// <ACE_SSL_SOCK_Stream>, and <ACE_Svc_Handler> classes. If the platform +// supports threads it uses a thread-per-connection concurrency model. +// Otherwise, it uses a single-threaded iterative server model. + +#include "ace/Svc_Handler.h" +#include "ace/Singleton.h" +#include "ace/Profile_Timer.h" +#include "ace/Get_Opt.h" +#include "ace/OS_NS_sys_select.h" + +#include "ace/SSL/SSL_SOCK_Acceptor.h" + +#include "SSL-server-fancy.h" + +ACE_RCSID (SSL_SAP, + SSL_server_fancy, + "$Id$") + +// Forward declaration. +class Handler; + +class Handler_Factory +{ + // = TITLE + // Creates the oneway or twoway handlers. +public: + Handler_Factory (void); + // Constructor. + + ~Handler_Factory (void); + // Destructor. + + int handle_events (void); + // Run the main event loop. + +private: + int init_acceptors (void); + // Initialize the acceptors. + + int create_handler (ACE_SSL_SOCK_Acceptor &acceptor, + Handler *(*handler_factory) (ACE_SSL_SOCK_Stream *), + const char *handler_type); + // Factory that creates the right kind of <Handler>. + + // = Factory functions. + + static Handler *make_twoway_handler (ACE_SSL_SOCK_Stream *); + // Create a twoway handler. + + static Handler *make_oneway_handler (ACE_SSL_SOCK_Stream *); + // Create a oneway handler. + + ACE_SSL_SOCK_Acceptor twoway_acceptor_; + // Twoway acceptor factory. + + ACE_SSL_SOCK_Acceptor oneway_acceptor_; + // Oneway acceptor factory. +}; + +class Handler : public ACE_Svc_Handler<ACE_SSL_SOCK_STREAM, ACE_NULL_SYNCH> +{ + // = TITLE + // Base class for the oneway and twoway handlers. + + friend class Handler_Factory; + // The factory has special permission. (to access svc ()). + +public: + virtual int open (void * = 0); + // Generic initialization method. + + virtual int close (u_long); + // Close down and delete this. + +protected: + + Handler (ACE_SSL_SOCK_Stream *ssl_stream); + // Constructor. + + int parse_header_and_allocate_buffer (char *&buf, + ACE_INT32 *len); + // Implement the generic code that's called from any of the subclass + // <run> methods to get the header and the buffer to read the data. + // This method factors out common code. + + virtual int run (void) = 0; + // Hook method called by the <svc> template method to do the actual + // protocol. Must be overridden by the subclass. + + virtual int svc (void); + // Template method entry point into the handler task. + + virtual void print_results (void); + // Print the results. + + size_t total_bytes_; + // Total number of bytes received. + + size_t message_count_; + // Number of messages received. + + ACE_Profile_Timer timer_; + // Keeps track of how much time we're using. + + ACE_SSL_SOCK_Stream *ssl_stream_; + //keep state information for a ssl_stream. +}; + +class Twoway_Handler : public Handler +{ + // = TITLE + // Performs the twoway protocol. +public: + + Twoway_Handler (ACE_SSL_SOCK_Stream *ssl_stream); + // Constructor. + +private: + + virtual int run (void); + // Template Method hook called by <svc>. + +}; + +class Oneway_Handler : public Handler +{ + // = TITLE +public: + Oneway_Handler (ACE_SSL_SOCK_Stream *ssl_stream); + // Constructor. + +private: + virtual int run (void); + // Template Method hook called by <svc>. + + virtual void print_results (void); + // Print the results. +}; + +u_short +Options::port (void) const +{ + return this->port_; +} + +int +Options::verbose (void) const +{ + return this->verbose_; +} + +int +Options::reply_message_len (void) const +{ + return this->reply_message_len_; +} + +Options::~Options (void) +{ +} + +Options::Options (void) + : verbose_ (0), + port_ (ACE_DEFAULT_SERVER_PORT), + reply_message_len_ (24) // Default to the approximate size of an + // GIOP reply message. +{ +} + +int +Options::parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt getopt (argc, argv, ACE_TEXT ("p:r:v"), 1); + + for (int c; (c = getopt ()) != -1; ) + switch (c) + { + case 'p': + this->port_ = ACE_OS::atoi (getopt.opt_arg ()); + break; + case 'r': + this->reply_message_len_ = ACE_OS::atoi (getopt.opt_arg ()); + break; + case 'v': + this->verbose_ = 1; + break; + default: + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) usage: %n [-p <port>] [-v]")), + -1); + } + + return 0; +} + +// Options Singleton. +typedef ACE_Singleton<Options, ACE_SYNCH_RECURSIVE_MUTEX> OPTIONS; + +Handler::Handler (ACE_SSL_SOCK_Stream *ssl_stream) + : total_bytes_ (0), + message_count_ (0), + ssl_stream_ (ssl_stream) + +{ +} + +int +Handler::open (void *) +{ + ACE_INET_Addr cli_addr; + + // Make sure we're not in non-blocking mode. + if (this->ssl_stream_-> disable (ACE_NONBLOCK) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("disable")), + 0); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) client %C connected from %d \n"), + cli_addr.get_host_name (), + cli_addr.get_port_number ())); + + return 0; +} + +int +Handler::close (u_long) +{ + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) closing down %@\n"), + this)); + + delete this->ssl_stream_; + delete this; + + return 0; +} + +int +Handler::svc (void) +{ + // Timer logic. + this->timer_.start (); + + // Invoke the hook method to run the specific test. + int result = this->run (); + + this->timer_.stop (); + + this->print_results (); + + return result; +} + +int +Handler::parse_header_and_allocate_buffer (char *&request, + ACE_INT32 *len) +{ + ssize_t result = this->ssl_stream_ -> recv_n ((void *) len, + sizeof (ACE_INT32)); + if (result == 0) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) connected closed\n"))); + return -1; + } + else if (result == -1 || result != sizeof (ACE_INT32)) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n"), + ACE_TEXT ("recv_n failed")), + -1); + else + { + *len = ntohl (*len); + ACE_NEW_RETURN (request, + char[*len], + -1); + } + + return 0; +} + +void +Handler::print_results (void) +{ +} + +Twoway_Handler::Twoway_Handler (ACE_SSL_SOCK_Stream* ssl_stream) + : Handler (ssl_stream) +{ +} + +// Function entry point into the twoway server task. + +int +Twoway_Handler::run (void) +{ + // Read data from client (terminate on error). + + char *request = 0; + + for (;;) + { + ACE_INT32 len = 0; + + if (parse_header_and_allocate_buffer (request, + &len) == -1) + return -1; + + // Subtract off the sizeof the length prefix. + ssize_t r_bytes = + this->ssl_stream_ -> recv_n (request, + len - sizeof (ACE_UINT32)); + + if (r_bytes == -1) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("recv"))); + break; + } + else if (r_bytes == 0) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) reached end of input, connection ") + ACE_TEXT ("closed by client\n"))); + break; + } + else if (OPTIONS::instance ()->verbose () + && ACE::write_n (ACE_STDOUT, + request, + r_bytes) != r_bytes) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("ACE::write_n"))); + else + { + ssize_t s_bytes = + (ssize_t) OPTIONS::instance ()->reply_message_len (); + + // Don't try to send more than is in the request buffer! + if (s_bytes > r_bytes) + s_bytes = r_bytes; + + if (this->ssl_stream_ -> send_n (request, + s_bytes) != s_bytes) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("send_n"))); + } + this->total_bytes_ += size_t (r_bytes); + this->message_count_++; + + delete [] request; + request = 0; + } + + delete [] request; + return 0; +} + +Oneway_Handler::Oneway_Handler (ACE_SSL_SOCK_Stream *ssl_stream) + : Handler (ssl_stream) +{ +} + +void +Oneway_Handler::print_results (void) +{ + ACE_Profile_Timer::ACE_Elapsed_Time et; + this->timer_.elapsed_time (et); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("\t\treal time = %f secs \n\t\tuser time = %f secs \n\t\tsystem time = %f secs\n"), + et.real_time, + et.user_time, + et.system_time)); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("\t\tmessages = %d\n\t\ttotal bytes = %d\n\t\tmbits/sec = %f\n\t\tusec-per-message = %f\n"), + this->message_count_, + this->total_bytes_, + (((double) this->total_bytes_ * 8) / et.real_time) / (double) (1024 * 1024), + ((et.user_time + et.system_time) / (double) this->message_count_) * ACE_ONE_SECOND_IN_USECS)); +} + +// Function entry point into the oneway server task. + +int +Oneway_Handler::run (void) +{ + // Read data from client (terminate on error). + + char *request = 0; + + for (;;) + { + ACE_INT32 len = 0; + + if (parse_header_and_allocate_buffer (request, + &len) == -1) + return -1; + + // Subtract off the sizeof the length prefix. + ssize_t r_bytes = + this->ssl_stream_ -> recv_n (request, + len - sizeof (ACE_UINT32)); + + if (r_bytes == -1) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("recv"))); + break; + } + else if (r_bytes == 0) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) reached end of input, connection ") + ACE_TEXT ("closed by client\n"))); + break; + } + else if (OPTIONS::instance ()->verbose () + && ACE::write_n (ACE_STDOUT, + request, + r_bytes) != r_bytes) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("ACE::write_n"))); + + this->total_bytes_ += size_t (r_bytes); + this->message_count_++; + delete [] request; + request = 0; + } + + delete [] request; + return 0; +} + +// Create a twoway handler. + +Handler * +Handler_Factory::make_twoway_handler (ACE_SSL_SOCK_Stream *ssl_stream) +{ + return new Twoway_Handler (ssl_stream); +} + +// Create a oneway handler. + +Handler * +Handler_Factory::make_oneway_handler (ACE_SSL_SOCK_Stream *ssl_stream) + +{ + return new Oneway_Handler (ssl_stream); +} + +int +Handler_Factory::init_acceptors (void) +{ + // Create the oneway and twoway server addresses. + ACE_INET_Addr twoway_server_addr (OPTIONS::instance ()->port ()); + ACE_INET_Addr oneway_server_addr (OPTIONS::instance ()->port () + 1); + + // Create acceptors, reuse the address. + if (this->twoway_acceptor_.open (twoway_server_addr, 1) == -1 + || this->oneway_acceptor_.open (oneway_server_addr, 1) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("open")), + -1); + else if (this->twoway_acceptor_.get_local_addr (twoway_server_addr) == -1 + || this->oneway_acceptor_.get_local_addr (oneway_server_addr) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("get_local_addr")), + -1); + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) starting twoway server at port %d and oneway server at port %d\n"), + twoway_server_addr.get_port_number (), + oneway_server_addr.get_port_number ())); + return 0; +} + +int +Handler_Factory::create_handler ( + ACE_SSL_SOCK_Acceptor &acceptor, + Handler * (*handler_factory) (ACE_SSL_SOCK_Stream* ), + const char *handler_type) +{ + ACE_SSL_SOCK_Stream* new_stream; + + ACE_NEW_RETURN (new_stream, ACE_SSL_SOCK_Stream, -1); + + if (acceptor.accept (*new_stream) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("accept")), + -1); + + Handler *handler; + + ACE_ALLOCATOR_RETURN (handler, + (*handler_factory) (new_stream), + -1); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) spawning %s handler\n"), + handler_type)); + + if (handler->open () == -1) + return -1; + +#if defined (ACE_MT_SAFE) + // Spawn a new thread and run the new connection in that thread of + // control using the <server> function as the entry point. + return handler->activate (); +#else + handler->svc (); + handler->close (0); + return 0; +#endif /* ACE_HAS_THREADS */ +} + +Handler_Factory::Handler_Factory (void) +{ +} + +Handler_Factory::~Handler_Factory (void) +{ + this->twoway_acceptor_.close (); + this->oneway_acceptor_.close (); +} + +// Run the main event loop. + +int +Handler_Factory::handle_events (void) +{ + if (this->init_acceptors () == -1) + return -1; + + fd_set handles; + + FD_ZERO (&handles); + FD_SET ((ACE_SOCKET) this->twoway_acceptor_.get_handle (), &handles); + FD_SET ((ACE_SOCKET) this->oneway_acceptor_.get_handle (), &handles); + + // Performs the iterative server activities. + + for (;;) + { + ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT); + fd_set temp = handles; + + int result = + ACE_OS::select (int (this->oneway_acceptor_.get_handle ()) + 1, + (fd_set *) &temp, + 0, + 0, + timeout); + if (result == -1) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) %p\n"), + ACE_TEXT ("select"))); + else if (result == 0 && OPTIONS::instance ()->verbose ()) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) select timed out\n"))); + else + { + if (FD_ISSET (this->twoway_acceptor_.get_handle (), + &temp)) + this->create_handler (this->twoway_acceptor_, + &Handler_Factory::make_twoway_handler, + "twoway"); + if (FD_ISSET (this->oneway_acceptor_.get_handle (), + &temp)) + this->create_handler (this->oneway_acceptor_, + &Handler_Factory::make_oneway_handler, + "oneway"); + } + } + + ACE_NOTREACHED (return 0;) +} + +int +ACE_TMAIN (int argc, ACE_TCHAR *argv[]) +{ + + ACE_SSL_Context *context = ACE_SSL_Context::instance (); + + context->certificate ("./dummy.pem", SSL_FILETYPE_PEM); + context->private_key ("./key.pem", SSL_FILETYPE_PEM); + + OPTIONS::instance ()->parse_args (argc, argv); + + Handler_Factory server; + + return server.handle_events (); +} + diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-fancy.h b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-fancy.h new file mode 100644 index 00000000000..fed1b513f90 --- /dev/null +++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-fancy.h @@ -0,0 +1,44 @@ +// -*- C++ -*- +// $Id$ + +// This file defines the Options class for SSL-server-fancy. +// IBM C++ compiler'd template auto-instantiator needs this in a separate file. + +#ifndef __ACE_SSL_SERVER_FANCY_H +#define __ACE_SSL_SERVER_FANCY_H + +class Options + // = TITLE + // Define the options for this test. +{ +public: + Options (void); + // Constructor. + + ~Options (void); + // Destructor. + + int parse_args (int argc, ACE_TCHAR *argv[]); + // Parse the command-line arguments. + + int verbose (void) const; + // Are we running in verbose mode? + + u_short port (void) const; + // Port number that we are listening at. + + int reply_message_len (void) const; + // Size of the reply message. + +private: + int verbose_; + // Are we running in verbose mode? + + u_short port_; + // Port number we listen at. + + size_t reply_message_len_; + // Size of the reply message. +}; + +#endif /* __ACE_SSL_SERVER_FANCY_H */ diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-poll.cpp b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-poll.cpp new file mode 100644 index 00000000000..83333ccc357 --- /dev/null +++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-poll.cpp @@ -0,0 +1,212 @@ +// $Id$ + +// IPC_SAP/poll server, which illustrates how to integrate the ACE +// SSL socket wrappers with the SVR4 <poll> system call to create a +// single-threaded concurrent server. This server program can be +// driven by the oneway test mode of SSL-client.cpp. + +#include "ace/OS_NS_stdlib.h" +#include "ace/OS_NS_unistd.h" +#include "ace/Time_Value.h" +#include "ace/SSL/SSL_SOCK_Acceptor.h" + +ACE_RCSID (SSL_SAP, + SSL_server_poll, + "$Id$") + +#if defined (ACE_HAS_POLL) + +#include "ace/SSL/SSL_SOCK_Stream.h" + +#include "ace/Log_Msg.h" +#include "ace/INET_Addr.h" +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_poll.h" + + +// Should we be verbose? +static int verbose = 0; + +// Max number of open handles. +static const int MAX_HANDLES = 200; + +struct Buffer_Info +{ + void *buf_; + // Pointer to the buffer. + + size_t len_; + // Length of the buffer. +}; + +// Array of <pollfd>'s. +static struct pollfd poll_array[MAX_HANDLES]; + +// Array of <Buffer_Info>. +static Buffer_Info buffer_array[MAX_HANDLES]; + +static void +init_poll_array (void) +{ + int i; + + for (i = 0; i < MAX_HANDLES; i++) + { + poll_array[i].fd = ACE_INVALID_HANDLE; + poll_array[i].events = POLLIN; + } +} + +static int +init_buffer (size_t index) +{ + ACE_INT32 len; + + if (ACE::recv_n (poll_array[index].fd, + (void *) &len, + sizeof (ACE_INT32)) != sizeof (ACE_INT32)) + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) %p\n", + "recv_n failed"), + -1); + else + { + len = ntohl (len); + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) reading messages of size %d from handle %d\n", + len, + poll_array[index].fd)); + + ACE_ALLOCATOR_RETURN (buffer_array[index].buf_, + ACE_OS::malloc (len), + -1); + buffer_array[index].len_ = len; + } + return 0; +} + +static void +handle_data (size_t &n_handles) +{ + // Handle pending logging messages first (s_handle + 1 is guaranteed + // to be lowest client descriptor). + + for (size_t index = 1; index < n_handles; index++) + { + if (ACE_BIT_ENABLED (poll_array[index].revents, POLLIN)) + { + // First time in, we need to initialize the buffer. + if (buffer_array[index].buf_ == 0 + && init_buffer (index) == -1) + { + ACE_ERROR ((LM_ERROR, + "(%P|%t) %p\n", + "init_buffer")); + continue; + } + + // Read data from client (terminate on error). + + ssize_t n = ACE::recv (poll_array[index].fd, + buffer_array[index].buf_, + buffer_array[index].len_); + // <recv> will not block in this case! + + if (n == -1) + ACE_ERROR ((LM_ERROR, + "%p\n", + "read failed")); + else if (n == 0) + { + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) closing oneway server at handle %d\n", + poll_array[index].fd)); + + // Handle client connection shutdown. + ACE_OS::close (poll_array[index].fd); + poll_array[index].fd = poll_array[--n_handles].fd; + + ACE_OS::free ((void *) buffer_array[index].buf_); + buffer_array[index].buf_ = 0; + buffer_array[index].len_ = 0; + } + else if (verbose) + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) %*s", + n, + buffer_array[index].buf_)); + } + } +} + +static void +handle_connections (ACE_SSL_SOCK_Acceptor &peer_acceptor, + size_t &n_handles) +{ + if (ACE_BIT_ENABLED (poll_array[0].revents, POLLIN)) + { + ACE_SSL_SOCK_Stream new_stream; + + ACE_INET_Addr client; + ACE_Time_Value nonblock (0, 0); + + // Handle all pending connection requests (note use of "polling" + // feature that doesn't block). + + while (ACE_OS::poll (poll_array, 1, nonblock) > 0) + if (peer_acceptor.accept (new_stream, &client) == -1) + ACE_OS::perror ("accept"); + else + { + const char *s = client.get_host_name (); + + ACE_ASSERT (s != 0); + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) client %s\n", + s)); + poll_array[n_handles++].fd = new_stream.get_handle (); + } + } +} + +int +main (int, char *[]) +{ + u_short port = ACE_DEFAULT_SERVER_PORT + 1; + + // Create a server end-point. + ACE_INET_Addr addr (port); + ACE_SSL_SOCK_Acceptor peer_acceptor (addr); + + ACE_HANDLE s_handle = peer_acceptor.get_handle (); + + init_poll_array (); + + poll_array[0].fd = s_handle; + + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) starting oneway server at port %d\n", + port)); + + for (size_t n_handles = 1;;) + { + // Wait for client I/O events (handle interrupts). + while (ACE_OS::poll (poll_array, n_handles) == -1 + && errno == EINTR) + continue; + + handle_data (n_handles); + handle_connections (peer_acceptor, n_handles); + } + + /* NOTREACHED */ + return 0; +} +#else +#include "ace/OS_NS_stdio.h" +int main (int, char *[]) +{ + ACE_OS::fprintf (stderr, "This feature is not supported\n"); + return 0; +} +#endif /* ACE_HAS_POLL */ diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-simple.cpp b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-simple.cpp new file mode 100644 index 00000000000..22535160cf0 --- /dev/null +++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-simple.cpp @@ -0,0 +1,366 @@ +// $Id$ + +// This example tests the features of the <ACE_SSL_SOCK_Acceptor>, +// <ACE_SSL_SOCK_Stream>, and <ACE_Svc_Handler> classes. + +#include "ace/Thread_Manager.h" +#include "ace/Handle_Set.h" +#include "ace/Profile_Timer.h" +#include "ace/OS_NS_sys_select.h" + +#include "ace/SSL/SSL_SOCK_Acceptor.h" + +ACE_RCSID(SSL_SAP, SSL_server_simple, "$Id$") + +// Are we running verbosely? +static int verbose = 1; + +// Function entry point into the twoway server task. + +int +twoway_server (ACE_SSL_SOCK_Stream &stream) +{ + ACE_INET_Addr cli_addr; + + // Make sure we're not in non-blocking mode. + if (stream.disable (ACE_NONBLOCK) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "disable"), + 0); + else if (stream.get_remote_addr (cli_addr) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "get_remote_addr"), + 0); + + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) client %s connected from %d\n", + cli_addr.get_host_name (), + cli_addr.get_port_number ())); + + size_t total_bytes = 0; + size_t message_count = 0; + + char *request = 0; + + // Read data from client (terminate on error). + + for (;;) + { + ACE_INT32 len; + + ssize_t r_bytes = stream.recv_n ((void *) &len, + sizeof (ACE_INT32)); + if (r_bytes == -1) + { + ACE_ERROR ((LM_ERROR, + "%p\n", + "recv")); + break; + } + else if (r_bytes == 0) + { + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) reached end of input, connection closed by client\n")); + break; + } + else if (r_bytes != sizeof (ACE_INT32)) + { + ACE_ERROR ((LM_ERROR, + "(%P|%t) %p\n", + "recv_n failed")); + break; + } + else + { + len = ntohl (len); + ACE_NEW_RETURN (request, + char [len], + 0); + } + + // Subtract off the sizeof the length prefix. + r_bytes = stream.recv_n (request, + len - sizeof (ACE_UINT32)); + if (r_bytes == -1) + { + ACE_ERROR ((LM_ERROR, + "%p\n", + "recv")); + break; + } + else if (r_bytes == 0) + { + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) reached end of input, connection closed by client\n")); + break; + } + else if (verbose + && ACE::write_n (ACE_STDOUT, + request, + r_bytes) != r_bytes) + ACE_ERROR ((LM_ERROR, + "%p\n", + "ACE::write_n")); + else if (stream.send_n (request, + r_bytes) != r_bytes) + ACE_ERROR ((LM_ERROR, + "%p\n", + "send_n")); + + total_bytes += size_t (r_bytes); + message_count++; + + delete [] request; + request = 0; + } + + // Close new endpoint (listening endpoint stays open). + stream.close (); + + delete [] request; + return 0; +} + +// Function entry point into the oneway server task. + +static int +oneway_server (ACE_SSL_SOCK_Stream &stream) +{ + ACE_INET_Addr cli_addr; + + // Make sure we're not in non-blocking mode. + if (stream.disable (ACE_NONBLOCK) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "disable"), + 0); + else if (stream.get_remote_addr (cli_addr) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "get_remote_addr"), + 0); + + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) client %s connected from %d\n", + cli_addr.get_host_name (), + cli_addr.get_port_number ())); + + // Timer business + ACE_Profile_Timer timer; + timer.start (); + + size_t total_bytes = 0; + size_t message_count = 0; + + char *request = 0; + + // Read data from client (terminate on error). + + for (;;) + { + ACE_INT32 len; + + ssize_t r_bytes = stream.recv_n ((void *) &len, + sizeof (ACE_INT32)); + if (r_bytes == -1) + { + ACE_ERROR ((LM_ERROR, + "%p\n", + "recv")); + break; + } + else if (r_bytes == 0) + { + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) reached end of input, connection closed by client\n")); + break; + } + else if (r_bytes != sizeof (ACE_INT32)) + { + ACE_ERROR ((LM_ERROR, + "(%P|%t) %p\n", + "recv_n failed")); + break; + } + else + { + len = ntohl (len); + ACE_NEW_RETURN (request, + char [len], + 0); + } + + // Subtract off the sizeof the length prefix. + r_bytes = stream.recv_n (request, + len - sizeof (ACE_UINT32)); + + if (r_bytes == -1) + { + ACE_ERROR ((LM_ERROR, + "%p\n", + "recv")); + break; + } + else if (r_bytes == 0) + { + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) reached end of input, connection closed by client\n")); + break; + } + else if (verbose + && ACE::write_n (ACE_STDOUT, request, r_bytes) != r_bytes) + ACE_ERROR ((LM_ERROR, + "%p\n", + "ACE::write_n")); + + total_bytes += size_t (r_bytes); + message_count++; + + delete [] request; + request = 0; + } + + timer.stop (); + + ACE_Profile_Timer::ACE_Elapsed_Time et; + timer.elapsed_time (et); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("\t\treal time = %f secs \n\t\tuser time = %f secs \n\t\tsystem time = %f secs\n"), + et.real_time, + et.user_time, + et.system_time)); + + double messages_per_sec = double (message_count) / et.real_time; + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("\t\tmessages = %d\n\t\ttotal bytes = %d\n\t\tmbits/sec = %f\n\t\tusec-per-message = %f\n\t\tmessages-per-second = %0.00f\n"), + message_count, + total_bytes, + (((double) total_bytes * 8) / et.real_time) / (double) (1024 * 1024), + (et.real_time / (double) message_count) * 1000000, + messages_per_sec < 0 ? 0 : messages_per_sec)); + + // Close new endpoint (listening endpoint stays open). + stream.close (); + + delete [] request; + return 0; +} + +static int +run_event_loop (u_short port) +{ + // Raise the socket handle limit to the maximum. + ACE::set_handle_limit (); + + // Create the oneway and twoway acceptors. + ACE_SSL_SOCK_Acceptor twoway_acceptor; + ACE_SSL_SOCK_Acceptor oneway_acceptor; + + // Create the oneway and twoway server addresses. + ACE_INET_Addr twoway_server_addr (port); + ACE_INET_Addr oneway_server_addr (port + 1); + + // Create acceptors, reuse the address. + if (twoway_acceptor.open (twoway_server_addr, 1) == -1 + || oneway_acceptor.open (oneway_server_addr, 1) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "open"), + 1); + else if (twoway_acceptor.get_local_addr (twoway_server_addr) == -1 + || oneway_acceptor.get_local_addr (oneway_server_addr) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "get_local_addr"), + 1); + + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) starting twoway server at port %d and oneway server at port %d\n", + twoway_server_addr.get_port_number (), + oneway_server_addr.get_port_number ())); + + // Keep these objects out here to prevent excessive constructor + // calls within the loop. + ACE_SSL_SOCK_Stream new_stream; + + ACE_Handle_Set handle_set; + handle_set.set_bit (twoway_acceptor.get_handle ()); + handle_set.set_bit (oneway_acceptor.get_handle ()); + + // Performs the iterative server activities. + + for (;;) + { + ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT); + ACE_Handle_Set temp = handle_set; + + int maxfd = int(oneway_acceptor.get_handle ()); + if (maxfd < int(twoway_acceptor.get_handle ())) + maxfd = int(twoway_acceptor.get_handle ()); + int result = ACE_OS::select (maxfd + 1, + (fd_set *) temp, + 0, + 0, + timeout); + if (result == -1) + ACE_ERROR ((LM_ERROR, + "(%P|%t) %p\n", + "select")); + else if (result == 0 && verbose) + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) select timed out\n")); + else + { + if (temp.is_set (twoway_acceptor.get_handle ())) + { + int r = twoway_acceptor.accept (new_stream); + while (r == -1 && errno == EAGAIN) + r = twoway_acceptor.accept (new_stream); + if (r == -1) + { + ACE_ERROR ((LM_ERROR, + "%p\n", + "accept")); + continue; + } + else + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) spawning twoway server\n")); + + // Run the twoway server. + twoway_server (new_stream); + } + if (temp.is_set (oneway_acceptor.get_handle ())) + { + if (oneway_acceptor.accept (new_stream) == -1) + { + ACE_ERROR ((LM_ERROR, "%p\n", "accept")); + continue; + } + else + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) spawning oneway server\n")); + + // Run the oneway server. + oneway_server (new_stream); + } + } + } + + /* NOTREACHED */ +} + +int +main (int argc, char *argv[]) +{ + u_short port = ACE_DEFAULT_SERVER_PORT; + + if (argc > 1) + port = ACE_OS::atoi (argv[1]); + + return run_event_loop (port); +} diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL-server.cpp b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server.cpp new file mode 100644 index 00000000000..8563067af03 --- /dev/null +++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server.cpp @@ -0,0 +1,430 @@ +// $Id$ + +// This example tests the features of the <ACE_SSL_SOCK_Acceptor>, +// <ACE_SSL_SOCK_Stream>, and <ACE_Svc_Handler> classes. If the platform +// supports threads it uses a thread-per-connection concurrency model. +// Otherwise, it uses a single-threaded iterative server model. + +#include "ace/Thread_Manager.h" +#include "ace/Handle_Set.h" +#include "ace/Profile_Timer.h" +#include "ace/OS_NS_sys_select.h" + +#include "ace/SSL/SSL_SOCK_Acceptor.h" + +ACE_RCSID(SSL_SAP, SSL_server, "$Id$") + +// Are we running verbosely? +static int verbose = 0; + +static void +run_server (ACE_THR_FUNC server, + ACE_SSL_SOCK_Stream * new_stream) +{ +#if defined (ACE_HAS_THREADS) + // Spawn a new thread and run the new connection in that thread of + // control using the <server> function as the entry point. + if (ACE_Thread_Manager::instance ()->spawn (server, + (void *) new_stream, + THR_DETACHED) == -1) + ACE_ERROR ((LM_ERROR, + "(%P|%t) %p\n", + "spawn")); +#else + (*server) ((void *) new_stream); +#endif /* ACE_HAS_THREADS */ +} + +// Function entry point into the twoway server task. + +static ACE_THR_FUNC_RETURN +twoway_server (void *arg) +{ + ACE_INET_Addr cli_addr; + ACE_SSL_SOCK_Stream * new_stream = (ACE_SSL_SOCK_Stream *) arg; + + // Make sure we're not in non-blocking mode. + if (new_stream->disable (ACE_NONBLOCK) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "disable"), + 0); + else if (new_stream->get_remote_addr (cli_addr) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "get_remote_addr"), + 0); + + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) client %s connected from %d\n", + cli_addr.get_host_name (), + cli_addr.get_port_number ())); + + size_t total_bytes = 0; + size_t message_count = 0; + + char *request = 0; + + // Read data from client (terminate on error). + + for (;;) + { + ACE_INT32 len; + + ssize_t r_bytes = new_stream->recv_n ((void *) &len, + sizeof (ACE_INT32)); + if (r_bytes == -1) + { + ACE_ERROR ((LM_ERROR, + "%p\n", + "recv")); + break; + } + else if (r_bytes == 0) + { + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) reached end of input, connection closed by client\n")); + break; + } + else if (r_bytes != sizeof (ACE_INT32)) + { + ACE_ERROR ((LM_ERROR, + "(%P|%t) %p\n", + "recv_n failed")); + break; + } + else + { + len = ntohl (len); + ACE_NEW_RETURN (request, + char [len], + 0); + } + + // Subtract off the sizeof the length prefix. + r_bytes = new_stream->recv_n (request, + len - sizeof (ACE_UINT32)); + if (r_bytes == -1) + { + ACE_ERROR ((LM_ERROR, + "%p\n", + "recv")); + break; + } + else if (r_bytes == 0) + { + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) reached end of input, " + "connection closed by client\n")); + break; + } + else if (verbose + && ACE::write_n (ACE_STDOUT, + request, + r_bytes) != r_bytes) + ACE_ERROR ((LM_ERROR, + "%p\n", + "ACE::write_n")); + else if (new_stream->send_n (request, + r_bytes) != r_bytes) + ACE_ERROR ((LM_ERROR, + "%p\n", + "send_n")); + + total_bytes += size_t (r_bytes); + message_count++; + + delete [] request; + request = 0; + } + + // Close new endpoint (listening endpoint stays open). + new_stream->close (); + + delete new_stream; + + delete [] request; + + return 0; +} + +// Function entry point into the oneway server task. + +static ACE_THR_FUNC_RETURN +oneway_server (void *arg) +{ + ACE_INET_Addr cli_addr; + ACE_SSL_SOCK_Stream * new_stream = (ACE_SSL_SOCK_Stream *) arg; + + // Make sure we're not in non-blocking mode. + if (new_stream->disable (ACE_NONBLOCK) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "disable"), + 0); + else if (new_stream->get_remote_addr (cli_addr) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "get_remote_addr"), + 0); + + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) client %s connected from %d\n", + cli_addr.get_host_name (), + cli_addr.get_port_number ())); + + // Timer business + ACE_Profile_Timer timer; + timer.start (); + + size_t total_bytes = 0; + size_t message_count = 0; + + char *request = 0; + + // Read data from client (terminate on error). + + for (;;) + { + ACE_INT32 len; + + ssize_t r_bytes = new_stream->recv_n ((void *) &len, + sizeof (ACE_INT32)); + if (r_bytes == -1) + { + ACE_ERROR ((LM_ERROR, + "%p\n", + "recv")); + break; + } + else if (r_bytes == 0) + { + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) reached end of input, connection closed by client\n")); + break; + } + else if (r_bytes != sizeof (ACE_INT32)) + { + ACE_ERROR ((LM_ERROR, + "(%P|%t) %p\n", + "recv_n failed")); + break; + } + else + { + len = ntohl (len); + ACE_NEW_RETURN (request, + char [len], + 0); + } + + // Subtract off the sizeof the length prefix. + r_bytes = new_stream->recv_n (request, + len - sizeof (ACE_UINT32)); + + if (r_bytes == -1) + { + ACE_ERROR ((LM_ERROR, + "%p\n", + "recv")); + break; + } + else if (r_bytes == 0) + { + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) reached end of input, connection closed by client\n")); + break; + } + else if (verbose + && ACE::write_n (ACE_STDOUT, request, r_bytes) != r_bytes) + ACE_ERROR ((LM_ERROR, + "%p\n", + "ACE::write_n")); + + total_bytes += size_t (r_bytes); + message_count++; + + delete [] request; + request = 0; + } + + timer.stop (); + + ACE_Profile_Timer::ACE_Elapsed_Time et; + timer.elapsed_time (et); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("\t\treal time = %f secs \n") + ACE_TEXT ("\t\tuser time = %f secs \n") + ACE_TEXT ("\t\tsystem time = %f secs\n"), + et.real_time, + et.user_time, + et.system_time)); + + double messages_per_sec = double (message_count) / et.real_time; + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("\t\tmessages = %d\n") + ACE_TEXT ("\t\ttotal bytes = %d\n") + ACE_TEXT ("\t\tmbits/sec = %f\n") + ACE_TEXT ("\t\tusec-per-message = %f\n") + ACE_TEXT ("\t\tmessages-per-second = %0.00f\n"), + message_count, + total_bytes, + (((double) total_bytes * 8) / et.real_time) / (double) (1024 * 1024), + (et.real_time / (double) message_count) * 1000000, + messages_per_sec < 0 ? 0 : messages_per_sec)); + + // Close new endpoint (listening endpoint stays open). + new_stream->close (); + + delete new_stream; + + delete [] request; + + return 0; +} + +static int +run_event_loop (u_short port) +{ + // Raise the socket handle limit to the maximum. + ACE::set_handle_limit (); + + // Create the oneway and twoway acceptors. + ACE_SSL_SOCK_Acceptor twoway_acceptor; + ACE_SSL_SOCK_Acceptor oneway_acceptor; + + // Create the oneway and twoway server addresses. + ACE_INET_Addr twoway_server_addr (port); + ACE_INET_Addr oneway_server_addr (port + 1); + + // Create acceptors, reuse the address. + if (twoway_acceptor.open (twoway_server_addr, 1) == -1 + || oneway_acceptor.open (oneway_server_addr, 1) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "open"), + 1); + else if (twoway_acceptor.get_local_addr (twoway_server_addr) == -1 + || oneway_acceptor.get_local_addr (oneway_server_addr) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + "get_local_addr"), + 1); + + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) starting twoway server at port %d and oneway server at port %d\n", + twoway_server_addr.get_port_number (), + oneway_server_addr.get_port_number ())); + + // Keep these objects out here to prevent excessive constructor + // calls within the loop. + + ACE_Handle_Set handle_set; + handle_set.set_bit (twoway_acceptor.get_handle ()); + handle_set.set_bit (oneway_acceptor.get_handle ()); + + ACE_SSL_SOCK_Stream * new_stream = 0; + + // Performs the iterative server activities. + for (;;) + { + ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT); + ACE_Handle_Set temp = handle_set; + + int result = ACE_OS::select (int (oneway_acceptor.get_handle ()) + 1, + (fd_set *) temp, + 0, + 0, + timeout); + if (result == -1) + ACE_ERROR ((LM_ERROR, + "(%P|%t) %p\n", + "select")); + else if (result == 0 && verbose) + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) select timed out\n")); + else + { + // A new ACE_SSL_SOCK_Stream must be initialized for each + // connection. However, it retains (SSL) state so simply + // initializing a new ACE_SSL_SOCK_Stream by passing it a + // handle isn't enough, nor is it allowed. Such a scheme is + // is sometimes done with the non-SSL aware + // ACE_SOCK_Stream. An ACE_SSL_SOCK_Stream should only be + // initialized by an ACE_SSL_SOCK_Acceptor (server side), or an + // ACE_SSL_SOCK_Connector (client side). + // + // It is also possible to copy or assign an + // ACE_SSL_SOCK_Stream since it implements both + // methods/operators. However, the user must ensure that + // the copy or assignment is atomic. + + if (temp.is_set (twoway_acceptor.get_handle ())) + { + ACE_NEW_RETURN (new_stream, + ACE_SSL_SOCK_Stream, + -1); + + if (twoway_acceptor.accept (*new_stream) == -1) + { + ACE_ERROR ((LM_ERROR, + "%p\n", + "accept")); + + delete new_stream; + + continue; + } + else + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) spawning twoway server\n")); + + // Run the twoway server. + run_server (twoway_server, + new_stream); + } + if (temp.is_set (oneway_acceptor.get_handle ())) + { + ACE_NEW_RETURN (new_stream, + ACE_SSL_SOCK_Stream, + -1); + + if (oneway_acceptor.accept (*new_stream) == -1) + { + ACE_ERROR ((LM_ERROR, "%p\n", "accept")); + + delete new_stream; + + continue; + } + else + ACE_DEBUG ((LM_DEBUG, + "(%P|%t) spawning oneway server\n")); + + // Run the oneway server. + run_server (oneway_server, + new_stream); + } + } + } + + /* NOTREACHED */ +} + +int +main (int argc, char *argv[]) +{ + ACE_SSL_Context *context = ACE_SSL_Context::instance (); + + context->certificate ("./dummy.pem", SSL_FILETYPE_PEM); + context->private_key ("./key.pem", SSL_FILETYPE_PEM); + + u_short port = ACE_DEFAULT_SERVER_PORT; + + if (argc > 1) + port = ACE_OS::atoi (argv[1]); + + return run_event_loop (port); +} diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL_SAP.mpc b/ACE/examples/IPC_SAP/SSL_SAP/SSL_SAP.mpc new file mode 100644 index 00000000000..675f104f4dc --- /dev/null +++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL_SAP.mpc @@ -0,0 +1,44 @@ +// -*- MPC -*- +// $Id$ + +project(*client) : aceexe, ssl { + exename = client + Source_Files { + SSL-client.cpp + } +} + +project(*client_simple) : aceexe, ssl { + exename = client-simple + Source_Files { + SSL-client-simple.cpp + } +} + +project(*server) : aceexe, ssl { + exename = server + Source_Files { + SSL-server.cpp + } +} + +project(*server_fancy) : aceexe, ssl { + exename = server-fancy + Source_Files { + SSL-server-fancy.cpp + } +} + +project(*server_poll) : aceexe, ssl { + exename = server-poll + Source_Files { + SSL-server-poll.cpp + } +} + +project(*server_simple) : aceexe, ssl { + exename = server-simple + Source_Files { + SSL-server-simple.cpp + } +} diff --git a/ACE/examples/IPC_SAP/SSL_SAP/dummy.pem b/ACE/examples/IPC_SAP/SSL_SAP/dummy.pem new file mode 100644 index 00000000000..d631a33b956 --- /dev/null +++ b/ACE/examples/IPC_SAP/SSL_SAP/dummy.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICaTCCAdICAQAwDQYJKoZIhvcNAQEEBQAwcjELMAkGA1UEBhMCVVMxCzAJBgNV +BAgTAkNBMQ8wDQYDVQQHEwZJcnZpbmUxDDAKBgNVBAoTA09DSTEMMAoGA1UECxMD +VEFPMREwDwYDVQQDEwhwcml5YW5rYTEWMBQGCSqGSIb3DQEJARYHcGdvbnRsYTAe +Fw0wMTAzMjkwNDM4NDZaFw0wMTA0MjgwNDM4NDZaMIGHMQswCQYDVQQGEwJVUzEL +MAkGA1UECBMCQ0ExDzANBgNVBAcTBklydmluZTEdMBsGA1UEChMUT2JqZWN0IENv +bXB1dGluZyBJbmMxEDAOBgNVBAsTB09DSStUQU8xETAPBgNVBAMTCHByaXlhbmth +MRYwFAYJKoZIhvcNAQkBFgdwZ29udGxhMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB +iQKBgQClC6z/bX1JHF1Hg06NCnBmsikEjViEdJFuqLOH3rXSGbm+2Eo+IO4dHlFS +u6+Ntk4olBZTuf0DqzyEgrOiN7cnKXpxJzb1cwCmVkvDQISMygf4o66+CHtF8o8Z +Sbi9F5u9W+MILaoCexEIVZqfHffcGxvm5O2MorBSQNka3NcC3wIDAQABMA0GCSqG +SIb3DQEBBAUAA4GBADuKX6kllE2sNdQYMbSzt5C/lcpgcsK0BR6L01cQA95b5TvL +HsKMeeeRj2npR4EPXY2gqgWTrKHZvf01aoKE5LuyzSQ+qfFMuEfo7+p9SYIuIrLD +5+J0wOwN0R0YZAEY5gCAqRGw26dwWDai+PASPsx0YXV1y9jBB1FFtUFgrpR8 +-----END CERTIFICATE----- diff --git a/ACE/examples/IPC_SAP/SSL_SAP/key.pem b/ACE/examples/IPC_SAP/SSL_SAP/key.pem new file mode 100644 index 00000000000..54ff8f0f488 --- /dev/null +++ b/ACE/examples/IPC_SAP/SSL_SAP/key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQClC6z/bX1JHF1Hg06NCnBmsikEjViEdJFuqLOH3rXSGbm+2Eo+ +IO4dHlFSu6+Ntk4olBZTuf0DqzyEgrOiN7cnKXpxJzb1cwCmVkvDQISMygf4o66+ +CHtF8o8ZSbi9F5u9W+MILaoCexEIVZqfHffcGxvm5O2MorBSQNka3NcC3wIDAQAB +AoGALYq/PexUeewdwTH2ZuzOf0gCEYN/PW19A/ABOii2OzdmDcdZFTO5AMfw4Mdx +dcUsY/4Y+xmDO5Pwqw/1yXleTDqvEKCgIEHN4NWnYYSiZOy3LBzQ8XaMZ7/2PCqc +s4EtesuRB2kZ7PH2R1vJfyGIxZPaO5MOFbs3QFnpBUjqOmECQQDQCYgnBcshCEro +gsrTjxtZiVHjmXEo0Uo2m4CBQW1PLJmmUXBzivGkVFfhjKULjwvso3BePfmzy9wP +7YFjVXN9AkEAyxjBXi2kYCcXfGQiNuIrLkyVXeGR2YWnhzS2nL1TjNngmCBbnj48 +qvoqOUQgFK0AeTe/x7lb4Cf24ejWF5vmiwJALensorAkpKWv4qD7IrXy00/7QsAa +uWd3eZXYRq6p8U9mmc5fgyCnNB1pR95CjsqDVza7FhGXipbzepBwffveAQJBAMKc +mxYyqDMW4nNoxDxRJs17xxkpwAdvAiQWB/JTnQ737DX5s7EDtECl7PXo6NDHIhAF +srigToCR6wl4gkYnNpcCQHmlfa9Duf3VJI/XeHE9ZU8vS4qgx0Ikfh01xCqWlsaq +nPRmtfktt4P8gxlryZCEPpRs9l/XwQY6tnpHr5EmV2Y= +-----END RSA PRIVATE KEY----- diff --git a/ACE/examples/IPC_SAP/SSL_SAP/local_data b/ACE/examples/IPC_SAP/SSL_SAP/local_data new file mode 100644 index 00000000000..c0119859a28 --- /dev/null +++ b/ACE/examples/IPC_SAP/SSL_SAP/local_data @@ -0,0 +1 @@ +I am Iron man! diff --git a/ACE/examples/IPC_SAP/SSL_SAP/summarize b/ACE/examples/IPC_SAP/SSL_SAP/summarize new file mode 100755 index 00000000000..ee8ffd2df25 --- /dev/null +++ b/ACE/examples/IPC_SAP/SSL_SAP/summarize @@ -0,0 +1,45 @@ +eval '(exit $?0)' && eval 'exec perl -w -S $0 ${1+"$@"}' + & eval 'exec perl -w -S $0 $argv:q' + if 0; + +# $Id$ +# +# Summarizes results from a series of runs of run_test, with +# different numbers of clients. Example usage: +# +# $ for i in 1 2 5 10 15 20 25 30 35 40 45 50; do ./run_test $i; done +# $ ./summarize +# +# The first three lines above let this script run without specifying the +# full path to perl, as long as it is in the user's PATH. +# Taken from perlrun man page. + +@files = glob 'client-*.log'; +@total_threads = (); + +foreach $file (@files) { + my ($i); + ($i = $file) =~ s/client-(\d+).log/$1/; + push @total_threads, $i; +} + +print "No.of threads\t\tAverage Latency\n\n"; + +foreach $total_threads (sort {$a <=> $b} @total_threads) { + undef $high_latency; + + $high_latency = 0; + open (FILE, "client-${total_threads}.log") || + die "$0: unable to open \"client-${total_threads}.log\"\n"; + while ($line = <FILE>) { + if ($line =~ /.*usec-per-message = ([\d\.]+)/) + { + $high_latency += $1 ; + $number++; + } + } + close FILE; + + printf "%3d\t\t\t%8f\n", + $total_threads, $high_latency/$number; +} |