Merge pull request #2216 from jwillemsen/jwi-cxxversionchecks
[ACE_TAO.git] / ACE / examples / IPC_SAP / SSL_SAP / SSL-client-simple.cpp
blob1107e306fb7215f2c541a7e27f66a8a74110a0ff
1 // This tests the features of the <ACE_SSL_SOCK_Connector> and
2 // <ACE_SSL_SOCK_Stream> classes. In addition, it can be used to test the
3 // oneway and twoway latency and throughput at the socket-level. This
4 // is useful as a baseline to compare against ORB-level performance
5 // for the same types of data.
7 #include "ace/OS_NS_string.h"
8 #include "ace/OS_NS_unistd.h"
9 #include "ace/INET_Addr.h"
10 #include "ace/Log_Msg.h"
11 #include "ace/Singleton.h"
12 #include "ace/Get_Opt.h"
13 #include "ace/High_Res_Timer.h"
14 #include "ace/Null_Mutex.h"
15 #include "ace/Truncate.h"
17 #include "ace/SSL/SSL_SOCK_Connector.h"
19 #include "SSL-client-simple.h"
21 Options::Options ()
22 : host_ (ACE_DEFAULT_SERVER_HOST),
23 port_ (ACE_DEFAULT_SERVER_PORT),
24 sleep_time_ (0, 0), // By default, don't sleep between calls.
25 message_len_ (0),
26 message_buf_ (0),
27 io_source_ (ACE_INVALID_HANDLE), // Defaults to using the generator.
28 iterations_ (10000),
29 oneway_ (1) // Make oneway calls the default.
31 ACE_OS::strcpy (quit_string_, "q");
34 Options::~Options ()
36 delete [] this->message_buf_;
39 // Options Singleton.
40 typedef ACE_Singleton<Options, ACE_Null_Mutex> OPTIONS;
42 int
43 Options::init ()
45 // Check for default case.
46 if (this->message_len_ == 0)
47 this->message_len_ = ACE_OS::strlen ("TAO");
49 this->message_len_ += sizeof (ACE_UINT32);
51 ACE_NEW_RETURN (this->message_buf_,
52 char[this->message_len_],
53 -1);
55 // Copy the length into the beginning of the message.
56 ACE_UINT32 length =
57 ntohl (ACE_Utils::truncate_cast<u_long> (this->message_len_));
59 ACE_OS::memcpy ((void *) this->message_buf_,
60 (void *) &length,
61 sizeof length);
63 ACE_OS::memset ((void *) (this->message_buf_ + sizeof (ACE_UINT32)),
64 'a',
65 this->message_len_ - sizeof (ACE_UINT32));
67 return 0;
70 size_t
71 Options::message_len () const
73 return this->message_len_;
76 const void *
77 Options::message_buf () const
79 return this->message_buf_;
82 ssize_t
83 Options::read (void *buf, size_t len, size_t &iteration)
85 if (this->io_source_ == ACE_STDIN)
86 return ACE_OS::read (ACE_STDIN, buf, len);
87 else if (iteration >= this->iterations_)
88 return 0;
89 else
91 ACE_OS::memcpy (buf,
92 this->message_buf (),
93 len);
94 ++iteration;
95 return ACE_Utils::truncate_cast<ssize_t> (len);
99 int
100 Options::parse_args (int argc, ACE_TCHAR *argv[])
102 //FUZZ: disable check_for_lack_ACE_OS
103 ACE_Get_Opt getopt (argc, argv, ACE_TEXT ("2h:i:m:p:q:sT:"), 1);
105 for (int c; (c = getopt ()) != -1; )
106 //FUZZ: enable check_for_lack_ACE_OS
107 switch (c)
109 case '2': // Disable the oneway client.
110 this->oneway_ = 0;
111 break;
112 case 'h':
113 this->host_ = getopt.opt_arg ();
114 break;
115 case 'i':
116 this->iterations_ = ACE_OS::atoi (getopt.opt_arg ());
117 break;
118 case 'm':
119 this->message_len_ = ACE_OS::atoi (getopt.opt_arg ());
120 break;
121 case 'p':
122 this->port_ = ACE_OS::atoi (getopt.opt_arg ());
123 break;
124 case 'q':
125 ACE_OS::strncpy (this->quit_string_,
126 ACE_TEXT_ALWAYS_CHAR (getopt.opt_arg ()),
127 QUIT_STRING_SIZE);
128 break;
129 case 's':
130 this->io_source_ = ACE_STDIN;
131 break;
132 case 'T':
133 this->sleep_time_.set (0, ACE_OS::atoi (getopt.opt_arg ()));
134 break;
135 default:
136 ACE_ERROR_RETURN ((LM_ERROR,
137 ACE_TEXT ("(%P|%t) usage: %n [-2] [-h <host>] ")
138 ACE_TEXT ("[-i iterations] [-m message-size] ")
139 ACE_TEXT ("[-p <port>] [-q <quit string>] ")
140 ACE_TEXT ("[-s] [-T <sleep_time>]\n")),
141 -1);
144 return this->init ();
147 u_short
148 Options::port () const
150 return this->port_;
153 const ACE_TCHAR *
154 Options::host () const
156 return this->host_;
159 const char *
160 Options::quit_string () const
162 return this->quit_string_;
165 const ACE_Time_Value &
166 Options::sleep_time () const
168 return this->sleep_time_;
171 char *
172 Options::shared_client_test (u_short port,
173 ACE_SSL_SOCK_Stream &cli_stream)
175 ACE_INET_Addr remote_addr (port, this->host_);
177 ACE_SSL_SOCK_Connector con;
179 if (con.connect (cli_stream,
180 remote_addr) == -1)
181 ACE_ERROR_RETURN ((LM_ERROR,
182 ACE_TEXT ("(%P|%t) %p\n"),
183 ACE_TEXT ("connection failed")),
185 else
186 ACE_DEBUG ((LM_DEBUG,
187 ACE_TEXT ("(%P|%t) connected to %C at port %d\n"),
188 remote_addr.get_host_name (),
189 remote_addr.get_port_number ()));
191 char *buf;
192 ACE_NEW_RETURN (buf,
193 char[this->message_len ()],
196 ACE_DEBUG ((LM_DEBUG,
197 ACE_TEXT ("(%P|%t) waiting...\n")));
199 return buf;
201 // Static function entry point to the oneway client service.
203 void
204 Options::oneway_client_test ()
206 ACE_SSL_SOCK_Stream cli_stream;
208 // Add 1 to the port to trigger the oneway test!
209 char *request = this->shared_client_test (this->port () + 1,
210 cli_stream);
211 if (request == 0)
212 return;
214 // This variable is allocated off the stack to obviate the need for
215 // locking.
216 size_t iteration = 0;
218 ACE_INT32 len =
219 ACE_Utils::truncate_cast<ACE_INT32> (this->message_len ());
221 ACE_DEBUG ((LM_DEBUG,
222 ACE_TEXT ("(%P|%t) starting oneway transmission\n")));
224 // Perform oneway transmission of data to server (correctly handles
225 // "incomplete writes").
227 for (ssize_t r_bytes;
228 (r_bytes = this->read (request, len, iteration)) > 0;
229 // Transmit at the proper rate.
230 ACE_OS::sleep (this->sleep_time ()))
231 if (ACE_OS::memcmp (request,
232 this->quit_string (),
233 ACE_OS::strlen (this->quit_string ())) == 0)
234 break;
235 else if (cli_stream.send_n (request, r_bytes) == -1)
237 ACE_ERROR ((LM_ERROR,
238 ACE_TEXT ("(%P|%t) %p\n"),
239 ACE_TEXT ("send_n")));
240 break;
243 // Close the connection.
244 cli_stream.close ();
246 delete [] request;
249 // Static function entry point to the twoway client service.
251 void
252 Options::twoway_client_test ()
254 ACE_SSL_SOCK_Stream cli_stream;
256 char *request = this->shared_client_test (this->port (),
257 cli_stream);
258 if (request == 0)
259 return;
261 // This variable is allocated off the stack to obviate the need for
262 // locking.
263 size_t iteration = 0;
265 // Timer business.
266 ACE_High_Res_Timer timer;
268 ACE_INT32 len =
269 ACE_Utils::truncate_cast<ACE_INT32> (this->message_len ());
271 ACE_DEBUG ((LM_DEBUG,
272 ACE_TEXT ("(%P|%t) starting twoway transmission\n")));
274 // Perform twoway transmission of data to server (correctly handles
275 // "incomplete writes").
277 for (ssize_t r_bytes;
278 (r_bytes = this->read (request, len, iteration)) > 0;
279 // Transmit at the proper rate.
280 ACE_OS::sleep (this->sleep_time ()))
281 if (ACE_OS::memcmp (request,
282 this->quit_string (),
283 ACE_OS::strlen (this->quit_string ())) == 0)
284 break;
286 // Transmit <request> to the server.
287 else
289 // Note that we use the incremental feature of the
290 // <ACE_High_Res_Timer> so that we don't get "charged" for the
291 // <ACE_OS::sleep> used to control the rate at which requests
292 // are sent.
293 timer.start_incr ();
295 if (cli_stream.send_n (request, r_bytes) == -1)
297 ACE_ERROR ((LM_ERROR,
298 ACE_TEXT ("(%P|%t) %p\n"),
299 ACE_TEXT ("send_n")));
300 break;
302 // Receive the reply from the server. Normally, it just sends
303 // back 24 bytes, which is typical for an IIOP reply.
304 else if (cli_stream.recv (request, r_bytes) <= 0)
306 ACE_ERROR ((LM_ERROR,
307 ACE_TEXT ("(%P|%t) %p\n"),
308 ACE_TEXT ("recv")));
309 break;
312 timer.stop_incr ();
315 ACE_Time_Value tv;
317 timer.elapsed_time_incr (tv);
318 double real_time = static_cast<double> (tv.sec () * ACE_ONE_SECOND_IN_USECS + tv.usec ());
319 double messages_per_sec = iteration * double (ACE_ONE_SECOND_IN_USECS) / real_time;
321 ACE_DEBUG ((LM_DEBUG,
322 ACE_TEXT ("(%t) messages = %d\n(%t) usec-per-message = %f\n(%t) messages-per-second = %0.00f\n"),
323 iteration,
324 real_time / double (iteration),
325 messages_per_sec < 0 ? 0 : messages_per_sec));
327 // Close the connection.
328 cli_stream.close ();
330 delete [] request;
333 void
334 Options::run ()
336 if (this->oneway_ == 0)
337 this->twoway_client_test ();
338 else
339 this->oneway_client_test ();
342 static int
343 run_client ()
345 // Raise the socket handle limit to the maximum.
346 ACE::set_handle_limit ();
348 OPTIONS::instance ()->run ();
350 return 0;
354 ACE_TMAIN (int argc, ACE_TCHAR *argv[])
356 // Initialize the logger.
357 ACE_LOG_MSG->open (argv[0]);
359 if (OPTIONS::instance ()->parse_args (argc, argv) == -1)
360 return -1;
362 // Run the client
363 run_client ();
365 return 0;