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"
22 : host_ (ACE_DEFAULT_SERVER_HOST
),
23 port_ (ACE_DEFAULT_SERVER_PORT
),
24 sleep_time_ (0, 0), // By default, don't sleep between calls.
27 io_source_ (ACE_INVALID_HANDLE
), // Defaults to using the generator.
29 oneway_ (1) // Make oneway calls the default.
31 ACE_OS::strcpy (quit_string_
, "q");
36 delete [] this->message_buf_
;
40 typedef ACE_Singleton
<Options
, ACE_Null_Mutex
> OPTIONS
;
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_
],
55 // Copy the length into the beginning of the message.
57 ntohl (ACE_Utils::truncate_cast
<u_long
> (this->message_len_
));
59 ACE_OS::memcpy ((void *) this->message_buf_
,
63 ACE_OS::memset ((void *) (this->message_buf_
+ sizeof (ACE_UINT32
)),
65 this->message_len_
- sizeof (ACE_UINT32
));
71 Options::message_len () const
73 return this->message_len_
;
77 Options::message_buf () const
79 return this->message_buf_
;
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_
)
95 return ACE_Utils::truncate_cast
<ssize_t
> (len
);
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
109 case '2': // Disable the oneway client.
113 this->host_
= getopt
.opt_arg ();
116 this->iterations_
= ACE_OS::atoi (getopt
.opt_arg ());
119 this->message_len_
= ACE_OS::atoi (getopt
.opt_arg ());
122 this->port_
= ACE_OS::atoi (getopt
.opt_arg ());
125 ACE_OS::strncpy (this->quit_string_
,
126 ACE_TEXT_ALWAYS_CHAR (getopt
.opt_arg ()),
130 this->io_source_
= ACE_STDIN
;
133 this->sleep_time_
.set (0, ACE_OS::atoi (getopt
.opt_arg ()));
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")),
144 return this->init ();
148 Options::port () const
154 Options::host () const
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_
;
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
,
181 ACE_ERROR_RETURN ((LM_ERROR
,
182 ACE_TEXT ("(%P|%t) %p\n"),
183 ACE_TEXT ("connection failed")),
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 ()));
193 char[this->message_len ()],
196 ACE_DEBUG ((LM_DEBUG
,
197 ACE_TEXT ("(%P|%t) waiting...\n")));
201 // Static function entry point to the oneway client service.
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,
214 // This variable is allocated off the stack to obviate the need for
216 size_t iteration
= 0;
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)
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")));
243 // Close the connection.
249 // Static function entry point to the twoway client service.
252 Options::twoway_client_test ()
254 ACE_SSL_SOCK_Stream cli_stream
;
256 char *request
= this->shared_client_test (this->port (),
261 // This variable is allocated off the stack to obviate the need for
263 size_t iteration
= 0;
266 ACE_High_Res_Timer timer
;
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)
286 // Transmit <request> to the server.
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
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")));
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"),
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"),
324 real_time
/ double (iteration
),
325 messages_per_sec
< 0 ? 0 : messages_per_sec
));
327 // Close the connection.
336 if (this->oneway_
== 0)
337 this->twoway_client_test ();
339 this->oneway_client_test ();
345 // Raise the socket handle limit to the maximum.
346 ACE::set_handle_limit ();
348 OPTIONS::instance ()->run ();
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)