Use =default for skeleton copy constructor
[ACE_TAO.git] / ACE / performance-tests / SCTP / Options_Manager.cpp
blobacd9373de2c10905fc0edebbd96979e59def2812
1 // -*- C++ -*-
2 #include "ace/Get_Opt.h"
3 #include "ace/os_include/netinet/os_in.h"
4 #include "ace/os_include/sys/os_types.h"
5 #include "ace/OS_NS_stdlib.h"
6 #include "ace/OS_NS_string.h"
8 // make sure that the code compiles cleanly even if SCTP is not
9 // available. If SCTP is not installed, program will exit early in
10 // main() with an error message.
11 #ifdef ACE_HAS_SCTP
12 extern "C" {
13 #include <netinet/sctp.h>
15 #else
16 #ifndef IPPROTO_SCTP
17 #define IPPROTO_SCTP 132 /* always the same value on every platform */
18 #endif
19 #endif
21 #include "Options_Manager.h"
23 // FUZZ: disable check_for_streams_include
24 #include "ace/streams.h"
26 #include "ace/OS_NS_stdio.h"
27 #include "ace/OS_NS_arpa_inet.h"
29 // Set default values
30 ACE_CDR::ULong Options_Manager::test_iterations=1000000;
31 ACE_CDR::Boolean Options_Manager::test_enable_nagle=0;
32 ACE_CDR::Long Options_Manager::test_transport_protocol=IPPROTO_SCTP;
33 ACE_CDR::Double Options_Manager::histogram_min_bin=0.0;
34 ACE_CDR::Double Options_Manager::histogram_max_bin=10000.0;
35 ACE_CDR::ULong Options_Manager::histogram_num_outliers=100;
36 ACE_CDR::ULong Options_Manager::histogram_bin_count=1000;
37 ACE_CDR::UShort Options_Manager::client_port = 0;
38 ACE_CDR::ULong Options_Manager::client_connect_addr=INADDR_ANY;
39 ACE_CDR::UShort Options_Manager::server_port = 45453;
40 ACE_TCHAR Options_Manager::server_host[Options_Manager::string_len];
41 ACE_CDR::ULong Options_Manager::server_accept_addr=INADDR_ANY;
42 ACE_CDR::UShort Options_Manager::payload_size_power_of_2=31;
43 ACE_CDR::ULong Options_Manager::secondary_connect_addrs[max_num_secondary_connect_addrs];
44 ACE_CDR::UShort Options_Manager::num_secondary_connect_addrs = 0;
45 ACE_CDR::ULong Options_Manager::secondary_accept_addrs[max_num_secondary_accept_addrs];
46 ACE_CDR::UShort Options_Manager::num_secondary_accept_addrs = 0;
47 ACE_CDR::UShort Options_Manager::_usage = 0;
48 ACE_CDR::UShort Options_Manager::_error = 0;
49 ACE_TCHAR Options_Manager::__program_name[Options_Manager::string_len];
50 ACE_CDR::Boolean Options_Manager::__initialized=0;
51 const ACE_TCHAR* Options_Manager::_error_message;
54 Options_Manager::Options_Manager(int argc, ACE_TCHAR **argv, ACE_TCHAR const * const opts_set)
56 if (!__initialized) {
57 // Set default values that were not set during static initialization
58 ACE_OS::strcpy(server_host, ACE_LOCALHOST);
60 // Remember argv[0]
61 if (ACE_OS::strlen(argv[0]) < Options_Manager::string_len)
62 ACE_OS::strcpy(__program_name, argv[0]);
63 else{
64 ACE_OS::strncpy(__program_name, argv[0], (Options_Manager::string_len-1));
65 __program_name[Options_Manager::string_len - 1] = '\0';
68 // Declare options with ACE_Get_Opt
69 int c;
70 ACE_Get_Opt * get_opt = 0;
71 if (!ACE_OS::strcmp(ACE_TEXT ("client-opts"), opts_set)){
72 get_opt = new ACE_Get_Opt(argc, argv, ACE_TEXT("c:nt:m:M:x:b:C:i:p:H:s:h"));
74 get_opt->long_option (ACE_TEXT ("test_iterations"), 'c',
75 ACE_Get_Opt::ARG_REQUIRED);
76 get_opt->long_option (ACE_TEXT ("test_enable_nagle"), 'n');
77 get_opt->long_option (ACE_TEXT ("test_transport_protocol"), 't',
78 ACE_Get_Opt::ARG_REQUIRED);
79 get_opt->long_option (ACE_TEXT ("histogram_min_bin"), 'm',
80 ACE_Get_Opt::ARG_REQUIRED);
81 get_opt->long_option (ACE_TEXT ("histogram_max_bin"), 'M',
82 ACE_Get_Opt::ARG_REQUIRED);
83 get_opt->long_option (ACE_TEXT ("histogram_num_outliers"), 'x',
84 ACE_Get_Opt::ARG_REQUIRED);
85 get_opt->long_option (ACE_TEXT ("histogram_bin_count"), 'b',
86 ACE_Get_Opt::ARG_REQUIRED);
87 get_opt->long_option (ACE_TEXT ("client_port"), 'C',
88 ACE_Get_Opt::ARG_REQUIRED);
89 get_opt->long_option (ACE_TEXT ("client_accept_addr"), 'i',
90 ACE_Get_Opt::ARG_REQUIRED);
91 get_opt->long_option (ACE_TEXT ("server_port"), 'p',
92 ACE_Get_Opt::ARG_REQUIRED);
93 get_opt->long_option (ACE_TEXT ("server_host"), 'H',
94 ACE_Get_Opt::ARG_REQUIRED);
95 get_opt->long_option (ACE_TEXT ("payload_size_power_of_2"), 's',
96 ACE_Get_Opt::ARG_REQUIRED);
97 get_opt->long_option (ACE_TEXT ("help"), 'h');
98 } else if (!ACE_OS::strcmp (ACE_TEXT ("server-opts"), opts_set)){
99 get_opt = new ACE_Get_Opt(argc, argv, ACE_TEXT("nt:p:a:u"));
100 get_opt->long_option (ACE_TEXT ("test_enable_nagle"), 'n');
101 get_opt->long_option (ACE_TEXT ("test_transport_protocol"), 't',
102 ACE_Get_Opt::ARG_REQUIRED);
103 get_opt->long_option (ACE_TEXT ("server_port"), 'p',
104 ACE_Get_Opt::ARG_REQUIRED);
105 get_opt->long_option (ACE_TEXT ("server_accept_addr"), 'a',
106 ACE_Get_Opt::ARG_REQUIRED);
107 get_opt->long_option (ACE_TEXT ("help"), 'h');
108 } else {
109 _error = 1;
110 _error_message = ACE_TEXT ("invalid options set specified");
111 delete get_opt;
112 return;
115 // Parse options with ACE_Get_Opt
116 while ((c = (*get_opt)()) != -1)
118 switch ((char) c)
120 case 'c':
121 test_iterations = ACE_OS::atoi(get_opt->opt_arg ());
122 break;
123 case 'n':
124 test_enable_nagle = 1;
125 break;
126 case 't':{
127 ACE_TCHAR const * const str = get_opt->opt_arg ();
128 if (!ACE_OS::strcmp (str, ACE_TEXT ("tcp")))
129 test_transport_protocol = IPPROTO_TCP;
130 else if (!ACE_OS::strcmp (str, ACE_TEXT ("sctp")))
131 test_transport_protocol = IPPROTO_SCTP;
132 else
133 test_transport_protocol = -1;
134 break;
136 case 'm':
137 histogram_min_bin = ACE_OS::strtod(get_opt->opt_arg (), 0);
138 break;
139 case 'M':
140 histogram_max_bin = ACE_OS::strtod(get_opt->opt_arg (), 0);
141 break;
142 case 'x':
143 histogram_num_outliers = ACE_OS::atoi(get_opt->opt_arg ());
144 break;
145 case 'b':
146 histogram_bin_count = ACE_OS::atoi(get_opt->opt_arg ());
147 break;
148 case 'C':
149 client_port = ACE_OS::atoi(get_opt->opt_arg ());
150 break;
151 case 'i':{
152 // The argument to this option is a comma-separated list
153 // of dotted-decimal ipv4 addresses.
155 // Create a writable copy of the options argument
156 ACE_TCHAR str[Options_Manager::string_len];
157 ACE_OS::strncpy(str, get_opt->opt_arg(), Options_Manager::string_len);
159 // Get a pointer to the first comma in the list
160 ACE_TCHAR *next_secondary_addr = ACE_OS::strchr(str, ',');
162 // If found, the comma is replaced with \0 and pointer
163 // updated to point to the string that begins immediately
164 // after the comma.
165 if (next_secondary_addr) {
166 *next_secondary_addr = '\0';
167 ++next_secondary_addr;
170 // Obtain the 32-bit, host-byte-order representation of
171 // the primary address.
172 struct in_addr foo;
173 int aton_retval = ACE_OS::inet_aton(ACE_TEXT_ALWAYS_CHAR (str),
174 &foo);
176 // If this representation was not obtained, terminate with
177 // an error.
178 if (!aton_retval) {
179 ACE_TCHAR error_message[Options_Manager::string_len + 100];
180 ACE_OS::strcpy
181 (error_message,
182 ACE_TEXT ("Could not make sense of primary address: "));
183 ACE_OS::strcat (error_message, str);
185 _error = 1;
186 _error_message = ACE_OS::strdup(error_message);
187 break;
190 // Otherwise, store the representation in the
191 // client_connect_addr member variable.
192 client_connect_addr = ntohl(foo.s_addr);
194 // ACE_DEBUG ((LM_DEBUG,
195 // "Primary connect addr: %s retval = %d\n",
196 // str,
197 // aton_retval));
199 // if (next_secondary_addr) {
200 // ACE_DEBUG ((LM_DEBUG,
201 // "Secondary addr(s) remaining to be parsed: %s\n",
202 // next_secondary_addr));
203 // } else {
204 // ACE_DEBUG ((LM_DEBUG,
205 // "No secondary addr remaining to be parsed.\n"));
206 // }
208 // The following loop parses secondary addresses from the
209 // list. The loop repeats as long as ACE_OS::strchr
210 // returns non-null (i.e., as long as yet another comma is
211 // found.
212 while (next_secondary_addr &&
213 num_secondary_connect_addrs <
214 max_num_secondary_connect_addrs) {
215 // Get a pointer to the next comma in the list.
216 ACE_TCHAR *next_next_secondary_addr = ACE_OS::strchr(next_secondary_addr, ',');
218 // If found, the comma is replaced with \0 and pointer
219 // updated to point to the string that begins immediately
220 // after the comma.
221 if (next_next_secondary_addr) {
222 *next_next_secondary_addr = '\0';
223 ++next_next_secondary_addr;
226 // Obtain the 32-bit, host-byte-order representation of
227 // a secondary address.
228 aton_retval =
229 ACE_OS::inet_aton(ACE_TEXT_ALWAYS_CHAR (next_secondary_addr),
230 &foo);
232 // If the representation was obtained without error,
233 // store it in the next available slot of the
234 // secondary_connect_addrs array. Otherwise, terminate
235 // with an error.
236 if (aton_retval) {
237 secondary_connect_addrs[num_secondary_connect_addrs++] =
238 ntohl(foo.s_addr);
239 } else {
240 ACE_TCHAR error_message[Options_Manager::string_len + 100];
241 ACE_OS::strcpy
242 (error_message,
243 ACE_TEXT ("Could not make sense of secondary address: "));
244 ACE_OS::strcat (error_message, next_secondary_addr);
245 _error = 1;
246 _error_message = ACE_OS::strdup(error_message);
247 break;
250 // ACE_DEBUG ((LM_DEBUG,
251 // "secondary_addr[%d] = %s retval = %d\n",
252 // num_secondary_connect_addrs - 1,
253 // next_secondary_addr,
254 // aton_retval));
256 next_secondary_addr = next_next_secondary_addr;
259 break;
261 case 'p':
262 server_port = ACE_OS::atoi(get_opt->opt_arg ());
263 break;
264 case 'a':{
265 // The argument to this option is a comma-separated list
266 // of dotted-decimal ipv4 addresses.
268 // Create a writable copy of the options argument
269 ACE_TCHAR str[Options_Manager::string_len];
270 ACE_OS::strncpy(str, get_opt->opt_arg(), Options_Manager::string_len);
272 // Get a pointer to the first comma in the list
273 ACE_TCHAR *next_secondary_addr = ACE_OS::strchr(str, ',');
275 // If found, the comma is replaced with \0 and pointer
276 // updated to point to the string that begins immediately
277 // after the comma.
278 if (next_secondary_addr) {
279 *next_secondary_addr = '\0';
280 ++next_secondary_addr;
283 // Obtain the 32-bit, host-byte-order representation of
284 // the primary address.
285 struct in_addr foo;
286 int aton_retval = ACE_OS::inet_aton (ACE_TEXT_ALWAYS_CHAR (str),
287 &foo);
289 // If this representation was not obtained, terminate with
290 // an error.
291 if (!aton_retval) {
292 ACE_TCHAR error_message[Options_Manager::string_len + 100];
293 ACE_OS::strcpy
294 (error_message,
295 ACE_TEXT ("Could not make sense of primary address: "));
296 ACE_OS::strcat (error_message, str);
298 _error = 1;
299 _error_message = ACE_OS::strdup(error_message);
300 break;
303 // Otherwise, store the representation in the
304 // server_accept_addr member variable.
305 server_accept_addr = ntohl(foo.s_addr);
307 // ACE_DEBUG ((LM_DEBUG,
308 // "Primary accept addr: %s retval = %d\n",
309 // str,
310 // aton_retval));
312 // if (next_secondary_addr) {
313 // ACE_DEBUG ((LM_DEBUG,
314 // "Secondary addr(s) remaining to be parsed: %s\n",
315 // next_secondary_addr));
316 // } else {
317 // ACE_DEBUG ((LM_DEBUG,
318 // "No secondary addr remaining to be parsed.\n"));
319 // }
321 // The following loop parses secondary addresses from the
322 // list. The loop repeats as long as ACE_OS::strchr
323 // returns non-null (i.e., as long as yet another comma is
324 // found.
325 while (next_secondary_addr &&
326 num_secondary_accept_addrs <
327 max_num_secondary_accept_addrs) {
328 // Get a pointer to the next comma in the list.
329 ACE_TCHAR *next_next_secondary_addr = ACE_OS::strchr(next_secondary_addr, ',');
331 // If found, the comma is replaced with \0 and pointer
332 // updated to point to the string that begins immediately
333 // after the comma.
334 if (next_next_secondary_addr) {
335 *next_next_secondary_addr = '\0';
336 ++next_next_secondary_addr;
339 // Obtain the 32-bit, host-byte-order representation of
340 // a secondary address.
341 aton_retval =
342 ACE_OS::inet_aton (ACE_TEXT_ALWAYS_CHAR (next_secondary_addr),
343 &foo);
345 // If the representation was obtained without error,
346 // store it in the next available slot of the
347 // secondary_accept_addrs array. Otherwise, terminate
348 // with an error.
349 if (aton_retval) {
350 secondary_accept_addrs[num_secondary_accept_addrs++] =
351 ntohl(foo.s_addr);
352 } else {
353 ACE_TCHAR error_message[Options_Manager::string_len + 100];
354 ACE_OS::strcpy
355 (error_message,
356 ACE_TEXT ("Could not make sense of secondary address: "));
357 ACE_OS::strcat (error_message, next_secondary_addr);
359 _error = 1;
360 _error_message = ACE_OS::strdup(error_message);
361 break;
364 // ACE_DEBUG ((LM_DEBUG,
365 // "secondary_addr[%d] = %s retval = %d\n",
366 // num_secondary_accept_addrs - 1,
367 // next_secondary_addr,
368 // aton_retval));
370 next_secondary_addr = next_next_secondary_addr;
373 break;
375 case 'H':{
376 ACE_TCHAR const * const str=get_opt->opt_arg();
377 if (ACE_OS::strlen (str) < Options_Manager::string_len)
378 ACE_OS::strcpy(server_host, str);
379 else{
380 ACE_OS::strncpy(server_host, str, (Options_Manager::string_len-1));
381 server_host[Options_Manager::string_len - 1] = '\0';
383 break;
385 case 's':
386 payload_size_power_of_2 = ACE_OS::atoi(get_opt->opt_arg ());
387 break;
388 case 'h':
389 _usage = 1;
390 break;
394 // Check option values
395 if (test_iterations < 1)
397 _error = 1;
398 _error_message = ACE_TEXT ("test_iterations must be no less than than 1");
401 if (histogram_min_bin < 0.0)
403 _error = 1;
404 _error_message = ACE_TEXT ("histogram_min_bin must be no less than 0.0");
407 if (histogram_max_bin < histogram_min_bin)
409 _error = 1;
410 _error_message = ACE_TEXT ("histogram_max_bin must be no less than histogram_min_bin");
413 if (histogram_num_outliers < 1)
415 _error = 1;
416 _error_message = ACE_TEXT ("histogram_num_outliers must be no less than 1");
419 if (histogram_bin_count < 1)
421 _error = 1;
422 _error_message = ACE_TEXT ("histogram_bin_count must be no less than 1");
425 if ((server_port < 1010 ||
426 server_port > 65000) && server_port != 0)
428 _error = 1;
429 _error_message = ACE_TEXT ("server_port must be between 1010 and 65000 inclusive, or zero.");
432 if ((!ACE_OS::strcmp(ACE_TEXT ("client-opts"), opts_set)) && payload_size_power_of_2 > 17)
434 _error = 1;
435 _error_message = ACE_TEXT("payload_size_power_of_2 must be specified between 0 and 16 inclusive");
438 if (test_transport_protocol == -1) {
439 _error = 1;
440 _error_message = ACE_TEXT ("test_transport_protocol may only take 'sctp' and 'tcp' as values");
443 __initialized = 1;
445 delete get_opt;
449 void Options_Manager::_show_usage(FILE* out, ACE_TCHAR const * const opts_set)
451 // Show usage message. KEEP THE DEFAULTS DISPLAYED HERE IN SYNC
452 // WITH THE DEFAULTS SET AT THE BEGINNING OF THE CONSTRUCTOR.
454 ACE_OS::fprintf (out, "%s - Measures round trip latency statistics of ACE synchronous\n",
455 ACE_TEXT_ALWAYS_CHAR (__program_name));
456 // indent past program name
457 for (unsigned int i=0;i<ACE_OS::strlen(__program_name);++i)
458 ACE_OS::fprintf (out, " ");
460 if (ACE_OS::strstr(__program_name, ACE_TEXT ("SOCK_STREAM_clt")) ||
461 ACE_OS::strstr(__program_name, ACE_TEXT ("SOCK_STREAM_srv")) ) {
462 ACE_OS::fprintf (out, " messaging (SOCK_Stream) using unmarshalled ACE_CDR::Octet.\n");
463 } else {
464 ACE_OS::fprintf (out, " messaging (SOCK_SEQPACK) using unmarshalled ACE_CDR::Octet.\n");
467 ACE_OS::fprintf (out, "USAGE: %s [ -<flag> [<val>] | --<name> [<val>] ]...\n\n",
468 ACE_TEXT_ALWAYS_CHAR (__program_name));
470 if (!ACE_OS::strcmp (ACE_TEXT ("client-opts"), opts_set)){
471 ACE_OS::fprintf (out, " Flag Args Option-Name Default\n"
472 " -c int test-iterations 1000000\n"
473 " -n none test-enable-nagle NO NAGLING\n");
474 if (ACE_OS::strstr(__program_name, ACE_TEXT ("SOCK_STREAM_clt"))) {
475 ACE_OS::fprintf (out, " -t str (sctp|tcp) test-transport-protocol sctp\n");
478 ACE_OS::fprintf (out, "\n");
480 ACE_OS::fprintf (out, " -m dbl histogram-min-bin 0\n"
481 " -M dbl histogram-max-bin 10000\n"
482 " -x int histogram-num-outliers 100\n"
483 " -b int histogram-bin-count 1000\n");
485 ACE_OS::fprintf (out, "\n");
487 ACE_OS::fprintf (out, " -C int client-port assigned by kernel\n"
488 " -i str client-connect-addr INADDR_ANY\n");
490 ACE_OS::fprintf (out, "\n");
492 ACE_OS::fprintf (out, " -p int server-port 45453\n"
493 " -H str server-host localhost\n");
495 ACE_OS::fprintf (out, "\n");
497 ACE_OS::fprintf (out, " -s int (0-16) payload-size-power-of-2 <MUST SET VALUE>\n");
499 ACE_OS::fprintf (out, "\n");
501 ACE_OS::fprintf (out, " -h none help\n");
503 ACE_OS::fprintf (out, "\n");
504 } else if (!ACE_OS::strcmp(ACE_TEXT ("server-opts"), opts_set)){
505 ACE_OS::fprintf (out, " Flag Args Option-Name Default\n"
506 " -n none test-enable-nagle NO NAGLING\n");
507 if (ACE_OS::strstr(__program_name, ACE_TEXT ("SOCK_STREAM_srv"))) {
508 ACE_OS::fprintf (out, " -t str (sctp|tcp) test-transport-protocol sctp\n");
511 ACE_OS::fprintf (out, "\n");
513 ACE_OS::fprintf (out, " -p int server-port 45453\n");
515 if (ACE_OS::strstr(__program_name, ACE_TEXT ("SOCK_SEQPACK_srv"))) {
516 ACE_OS::fprintf (out, " -a w.x.y.z,a.b.c.d,... server-accept-addr INADDR_ANY\n"
517 " (comma-separated \n"
518 " list of one or more \n"
519 " addresses) \n");
520 } else {
521 ACE_OS::fprintf (out, " -a w.x.y.z server-accept-addr INADDR_ANY\n");
524 ACE_OS::fprintf (out, " -h none help\n");
526 ACE_OS::fprintf (out, "\n");
527 } else {
528 ACE_OS::fprintf (out, "Invalid options set specified.\n");
531 return;