1 //=============================================================================
3 * @file Network_Adapters_Test.cpp
5 * Tests the ICMP-echo support in ACE.
7 * @author Robert S. Iakobashvili <coroberti@gmail.com> <coroberti@walla.co.il> Gonzalo A. Diethelm <gonzalo.diethelm@aditiva.com>
9 //=============================================================================
12 // We need this to be able to check for ACE_HAS_ICMP_SUPPORT
13 #include "ace/config-all.h"
14 #include "test_config.h"
16 #if defined (ACE_HAS_ICMP_SUPPORT) && (ACE_HAS_ICMP_SUPPORT == 1) && \
17 !defined ACE_LACKS_GETPROTOBYNAME
20 #include "ace/Get_Opt.h"
21 #include "ace/Signal.h"
22 #include "ace/High_Res_Timer.h"
23 #include "ace/Atomic_Op.h"
24 #include "ace/Sched_Params.h"
25 #include "ace/Reactor.h"
26 #include "ace/Timer_Queue.h"
27 #include "ace/OS_NS_string.h"
28 #include "ace/OS_NS_signal.h"
29 #include "ace/Timer_Heap.h"
32 #include "Network_Adapters_Test.h"
35 * There are two major uses of the functionality:
37 * 1. to check a local network adapter;
38 * 2. to check which of the remote CEs (computer elements) are alive.
40 * For the first purpose we are creating a raw socket, binding it to
41 * the IP-address in question (adapter to be monitored), and are
42 * sending via the adapter ICMP echo-checks to a list of 3rd party
43 * ping-points. If at least a single 3rd party replies us within a
44 * configurable timeout by an ICMP-reply, our adapter is OK. If not, we
45 * may wish to repeat ICMP-probing once or twice more. We may also
46 * wish to make such tests regular with a configurable interval in seconds.
48 * For the second purpose we are creating a raw socket, and without
49 * binding it are sending via any our CE's adapter ICMP echo-checks to
50 * a list of CEs to be monitored. An array of chars (named ping_status
51 * in main ()), corresponding to the array of addresses
52 * (ping_points_addrs in main ()), contains status of each monitored
53 * CE. When we get ICMP-reply from a ping_points_addrs[I] IP-address,
54 * we are placing 0 to the ping_status[I]. The ICMP-probing may be
55 * configured to test 2-3 times each pinged CE. We may also wish to
56 * make such tests regular with a configurable interval in seconds.
58 * Command line options:
60 * -b IPv4 of the interface to bind to the socket (only for the
61 * purpose 1), e.g. -b 192.168.5.5;
63 * -p IPv4 addresses of the remote CEs, which we are going to check
64 * (purpose 2), or they are 3rd points for the purpose 1,
65 * e.g. -p 192.168.5.120: 192.168.5.122: 192.168.5.125
67 * -w milliseconds to wait for echo-reply, on lan 100-200 msec, on
68 * WAN may be 2000-5000 msec, for GPRS may reach 10000 - 20000
71 * -t as we are doing such checks regularly time in seconds between
74 * In main we are activating by open () an instance of Echo_Handler
77 * Repeats_Handler serves to repeat the checks each
78 * repeats_seconds_timer seconds.
80 * Stop_Handler contains a list of handlers to be stopped and is
81 * supposed to close this business.
83 * Attention: Running the test without parameters (just using defaults)
84 * makes pinging to the loopback address. Therefore, the raw socket
85 * sees both ICMP_ECHO and ICMP_ECHOREPLY with the first output in log
86 * as not a ICMP_ECHOREPLY message and further ICMP_ECHOREPLY
87 * received. Don't worry, be happy - it's ok.
89 Echo_Handler::Echo_Handler ()
95 delete_success_status_ (0),
96 max_attempts_num_ (0),
98 connect_to_remote_ (0)
102 Echo_Handler::~Echo_Handler ()
104 ACE_DEBUG ((LM_DEBUG
,
105 ACE_TEXT ("(%P|%t) Echo_Handler::~Echo_Handler - entered.\n")));
107 this->ping_socket ().close ();
108 if (this->remote_addrs_
)
110 delete [] this->remote_addrs_
;
111 this->remote_addrs_
= 0;
113 if (this->success_status_
&& this->delete_success_status_
)
115 delete this->success_status_
;
117 this->success_status_
= 0;
121 ACE_TEXT ("(%P|%t) Echo_Handler::~Echo_Handler - completed.\n")));
125 Echo_Handler::open (ACE_Reactor
* const reactor
,
126 ACE_Time_Value
const & reply_wait
,
127 ACE_INET_Addr
const & remote_addr
,
128 ACE_TCHAR
* success_status
,
129 size_t max_attempts_num
,
130 ACE_Addr
const & local_addr
,
131 int connect_to_remote
)
133 if (this->reactor ())
134 ACE_ERROR_RETURN ((LM_ERROR
,
135 ACE_TEXT ("(%P|%t) Echo_Handler::open - failed: ")
136 ACE_TEXT ("reactor is already set.\n")),
139 ACE_ERROR_RETURN ((LM_ERROR
,
140 ACE_TEXT ("(%P|%t) Echo_Handler::open - failed : ")
141 ACE_TEXT ("NULL pointer to reactor provided.\n")),
144 this->reactor (reactor
);
145 this->reply_wait_
= reply_wait
;
147 if (this->remote_addrs_
)
148 ACE_ERROR_RETURN ((LM_ERROR
,
149 ACE_TEXT ("(%P|%t) Echo_Handler::open - failed: ")
150 ACE_TEXT ("remote_addrs_ already initialized.\n")),
153 ACE_NEW_RETURN (this->remote_addrs_
, ACE_INET_Addr
, -1);
155 // now copy to keep it locally
156 this->remote_addrs_
[0] = remote_addr
;
157 this->number_remotes_
= 1;
158 if (this->success_status_
)
159 ACE_ERROR_RETURN ((LM_ERROR
,
160 ACE_TEXT ("(%P|%t) Echo_Handler::open - failed: ")
161 ACE_TEXT ("success_status_ already initialized.\n")),
164 if (! success_status
)
166 ACE_NEW_RETURN (this->success_status_
, ACE_TCHAR
, -1);
167 this->delete_success_status_
= 1;
171 this->success_status_
= success_status
;
174 // place 'failed' to the array.
175 this->success_status_
[0] = 1;
177 this->max_attempts_num_
= max_attempts_num
;
178 this->current_attempt_
= this->max_attempts_num_
;
180 if (this->ping_socket ().open (local_addr
) == -1)
181 ACE_ERROR_RETURN ((LM_ERROR
,
182 ACE_TEXT ("(%P|%t) Echo_Handler::open: %p\n"),
183 ACE_TEXT ("ping_socket_")),
186 this->connect_to_remote_
= connect_to_remote
;
188 // Register with the reactor for input.
189 if (this->reactor ()->register_handler (this,
190 ACE_Event_Handler::READ_MASK
) == -1)
191 ACE_ERROR_RETURN ((LM_ERROR
,
192 ACE_TEXT ("(%P|%t) Echo_Handler::open: %p\n"),
193 ACE_TEXT ("register_handler for input")),
199 Echo_Handler::open (ACE_Reactor
* const reactor
,
200 ACE_Time_Value
const & reply_wait
,
201 ACE_INET_Addr
const remote_addrs
[],
202 size_t number_remotes
,
203 ACE_TCHAR
*success_status
,
204 size_t max_attempts_num
,
205 ACE_Addr
const & local_addr
)
207 if (this->reactor ())
208 ACE_ERROR_RETURN ((LM_ERROR
,
209 ACE_TEXT ("(%P|%t) Echo_Handler::open - failed: ")
210 ACE_TEXT ("reactor is already set.\n")),
213 //FUZZ: disable check_for_NULL
215 ACE_ERROR_RETURN ((LM_ERROR
,
216 ACE_TEXT ("(%P|%t) Echo_Handler::open - failed: NULL ")
217 ACE_TEXT ("pointer to reactor provided.\n")),
219 //FUZZ: enable check_for_NULL
221 this->reactor (reactor
);
222 this->reply_wait_
= reply_wait
;
225 ACE_ERROR_RETURN ((LM_ERROR
,
226 ACE_TEXT ("(%P|%t) Echo_Handler::open - failed: ")
227 ACE_TEXT ("NULL remote_addr pointer provided.\n")),
231 ACE_ERROR_RETURN ((LM_ERROR
,
232 ACE_TEXT ("(%P|%t) Echo_Handler::open - failed: ")
233 ACE_TEXT ("size of remote_addrs array is 0.\n")),
236 this->number_remotes_
= number_remotes
;
238 if (this->remote_addrs_
)
239 ACE_ERROR_RETURN ((LM_ERROR
,
240 ACE_TEXT ("(%P|%t) Echo_Handler::open - failed: ")
241 ACE_TEXT ("remote_addrs_ already initialized.\n")),
244 ACE_NEW_RETURN (this->remote_addrs_
,
245 ACE_INET_Addr
[this->number_remotes_
],
248 // now copy to keep them locally
249 for (size_t i
= 0; i
< this->number_remotes_
; ++i
)
251 this->remote_addrs_
[i
] = remote_addrs
[i
];
254 if (this->success_status_
)
255 ACE_ERROR_RETURN ((LM_ERROR
,
256 ACE_TEXT ("(%P|%t) Echo_Handler::open - failed: ")
257 ACE_TEXT ("success_status_ already initialized.\n")),
260 if (! success_status
)
262 ACE_NEW_RETURN (this->success_status_
,
263 ACE_TCHAR
[this->number_remotes_
],
265 this->delete_success_status_
= 1;
269 this->success_status_
= success_status
;
272 // place 'failed' to the this->success_status_ array.
273 for (size_t j
= 0; j
< this->number_remotes_
; ++j
)
275 this->success_status_
[j
] = 1;
278 this->max_attempts_num_
= max_attempts_num
;
279 this->current_attempt_
= this->max_attempts_num_
;
281 // If this process doesn't have privileges to open a raw socket, log
282 // a warning instead of an error.
283 if (this->ping_socket ().open (local_addr
) == -1)
285 if (errno
== EPERM
|| errno
== EACCES
)
286 ACE_ERROR_RETURN ((LM_WARNING
,
287 ACE_TEXT ("(%P|%t) Echo_Handler::open: ")
288 ACE_TEXT ("ping_socket_: insufficient privs to ")
289 ACE_TEXT ("run this test\n")),
292 ACE_ERROR_RETURN ((LM_ERROR
,
293 ACE_TEXT ("(%P|%t) Echo_Handler::open: %p\n"),
294 ACE_TEXT ("ping_socket_")),
298 // register with the reactor for input
299 if (this->reactor ()->register_handler (this,
300 ACE_Event_Handler::READ_MASK
) == -1)
301 ACE_ERROR_RETURN ((LM_ERROR
,
302 ACE_TEXT ("(%P|%t) Echo_Handler::open: %p\n"),
303 ACE_TEXT ("register_handler for input")),
309 Echo_Handler::ping_socket ()
311 return this->ping_socket_
;
315 Echo_Handler::dispatch_echo_checks (int first_call
)
317 // Set ones , if this is the first call (not from handle_timeout)
320 for (size_t j
= 0; j
< this->number_remotes_
; ++j
)
322 this->success_status_
[j
] = 1;
324 this->current_attempt_
= this->max_attempts_num_
;
328 for (size_t i
= 0; i
< this->number_remotes_
; ++i
)
330 if (this->success_status_
[i
] != 0)
332 if (this->ping_socket ().send_echo_check (
333 this->remote_addrs_
[i
],
334 this->connect_to_remote_
) == -1)
337 ACE_TEXT ("(%P|%t) Echo_Handler::dispatch_echo_checks - ")
338 ACE_TEXT ("failed for this->remote_addrs_[%d].\n"),
345 this->reactor ()->schedule_timer (this,
348 this->reply_wait_
)) == -1)
349 ACE_ERROR_RETURN ((LM_ERROR
,
350 ACE_TEXT ("(%P|%t) Echo_Handler::dispatch_echo_checks:")
352 ACE_TEXT ("schedule_timer")),
358 Echo_Handler::handle_close (ACE_HANDLE
, ACE_Reactor_Mask
)
360 ACE_DEBUG ((LM_DEBUG
,
361 ACE_TEXT ("(%P|%t) Echo_Handler::handle_close - started.\n")));
364 this->ping_socket ().close ();
367 this->reactor ()->cancel_timer (this);
370 this->reactor ()->remove_handler (this,
371 ACE_Event_Handler::ALL_EVENTS_MASK
|
372 ACE_Event_Handler::DONT_CALL
);
375 ACE_DEBUG ((LM_DEBUG
,
376 ACE_TEXT ("(%P|%t) Echo_Handler::handle_close - completed.\n")));
381 Echo_Handler::get_handle () const
383 return ((ACE_ICMP_Socket
&) this->ping_socket_
).get_handle ();
387 Echo_Handler::handle_input (ACE_HANDLE
)
389 ACE_DEBUG ((LM_DEBUG
,
390 ACE_TEXT ("(%P|%t) Echo_Handler::handle_input - ")
391 ACE_TEXT ("activity occurred on handle %d!\n"),
392 this->ping_socket ().get_handle ()));
394 ACE_TCHAR buf
[BUFSIZ
];
395 ACE_OS::memset (buf
, 0, sizeof buf
);
400 // Receive an <n> byte <buf> from the datagram socket
401 // (uses<recvfrom(3)>).
403 this->ping_socket ().recv (this->ping_socket ().icmp_recv_buff (),
404 ACE_Ping_Socket::PING_BUFFER_SIZE
,
409 // Complain and leave, but keep registered, returning 0.
410 ACE_ERROR_RETURN ((LM_ERROR
,
411 ACE_TEXT ("(%P|%t) Echo_Handler::handle_input - ")
412 ACE_TEXT ("%p: bad read\n"),
413 ACE_TEXT ("client")),
418 // Complain and leave
419 ACE_ERROR_RETURN ((LM_ERROR
,
420 ACE_TEXT ("(%P|%t) Echo_Handler::handle_input - ")
421 ACE_TEXT ("closing daemon (fd = %d)\n"),
422 this->get_handle ()),
428 ACE_TEXT ("(%P|%t) Echo_Handler::handle_input - ")
429 ACE_TEXT ("message from %d bytes received.\n"),
432 if (! this->ping_socket ().process_incoming_dgram (
433 this->ping_socket ().icmp_recv_buff (),
436 for (size_t k
= 0; k
<this->number_remotes_
; ++k
)
438 if (addr
.is_ip_equal (this->remote_addrs_
[k
]))
440 if (addr
.addr_to_string (buf
, sizeof buf
) == -1)
442 ACE_ERROR ((LM_ERROR
,
444 ACE_TEXT ("can't obtain peer's address")));
450 ACE_TEXT ("(%P|%t) Echo_Handler::handle_input - ")
451 ACE_TEXT ("ECHO_REPLY received ")
452 ACE_TEXT ("from %s; marking this peer alive\n"),
455 // mark as successful
456 this->success_status_
[k
] = 0;
468 Echo_Handler::handle_timeout (ACE_Time_Value
const &,
471 ACE_DEBUG ((LM_DEBUG
,
472 ACE_TEXT ("(%P|%t) Echo_Handler::handle_timeout - ")
473 ACE_TEXT ("timer for ping_socket_ with handle %d.\n"),
474 this->ping_socket ().get_handle ()));
476 int need_to_proceed
= 0;
478 for (size_t i
= 0; i
< this->number_remotes_
; ++i
)
480 if (this->success_status_
[i
])
484 ACE_DEBUG ((LM_DEBUG
,
485 ACE_TEXT ("(%P|%t) Echo_Handler::handle_timeout - ")
486 ACE_TEXT ("this->success_status_[%d] is not zero. ")
487 ACE_TEXT ("Need to proceed echo-checks.\n"), i
));
492 if (!need_to_proceed
)
494 ACE_DEBUG ((LM_DEBUG
,
495 ACE_TEXT ("(%P|%t) Echo_Handler::handle_timeout - ")
496 ACE_TEXT ("need_to_proceed == 0. ")
497 ACE_TEXT ("Completed echo-checks.\n")));
500 if (!this->current_attempt_
|| !need_to_proceed
)
502 ACE_DEBUG ((LM_DEBUG
,
503 ACE_TEXT ("(%P|%t) Echo_Handler::handle_timeout - ")
504 ACE_TEXT ("completed ECHO-checks for handle (%d).\n"),
505 this->ping_socket ().get_handle ()));
506 return -1; // to de-register from Reactor and make clean-up
510 if (this->current_attempt_
)
512 --this->current_attempt_
;
517 ACE_TEXT ("(%P|%t) Echo_Handler::handle_timeout - attempt %d.\n"),
518 this->current_attempt_
));
520 this->dispatch_echo_checks ();
525 Echo_Handler::does_echo_test_successful ()
527 for (size_t i
= 0; i
< this->number_remotes_
; ++i
)
529 if (!this->success_status_
[i
])
538 Stop_Handler::Stop_Handler (ACE_Reactor
* const reactor
)
539 : counter_ ((counter_sig
) 1)
541 this->reactor (reactor
);
542 ACE_OS::memset (this->handlers_to_stop_
,
544 sizeof this->handlers_to_stop_
);
547 Stop_Handler::~Stop_Handler ()
549 ACE_DEBUG ((LM_INFO
, ACE_TEXT ("(%P|%t) Stop_Handler::~Stop_Handler.\n")));
553 Stop_Handler::open ()
555 // Register the signal handler object to catch the signals.
557 if (this->reactor ()->register_handler (SIGINT
, this) == -1)
558 ACE_ERROR_RETURN ((LM_ERROR
,
559 ACE_TEXT ("(%P|%t) Stop_Handler::open: %p <%d>\n"),
560 ACE_TEXT ("register_handler for SIGINT"), SIGINT
),
562 this->registered_signals_
.sig_add (SIGINT
);
563 #endif /* SIGINT != 0 */
566 if (this->reactor ()->register_handler (SIGTERM
, this) == -1)
567 ACE_ERROR_RETURN ((LM_ERROR
,
568 ACE_TEXT ("(%P|%t) Stop_Handler::open: %p <%d>\n"),
569 ACE_TEXT ("register_handler for SIGTERM"), SIGTERM
),
571 this->registered_signals_
.sig_add (SIGTERM
);
572 #endif /* SIGTERM != 0 */
575 if (this->reactor ()->register_handler (SIGQUIT
, this) == -1)
576 ACE_ERROR_RETURN ((LM_ERROR
,
577 ACE_TEXT ("(%P|%t) Stop_Handler::open: %p <%d>\n"),
578 ACE_TEXT ("register_handler for SIGQUIT"), SIGQUIT
),
580 this->registered_signals_
.sig_add (SIGQUIT
);
581 #endif /* SIGQUIT != 0 */
586 Stop_Handler::handle_signal (int signum
, siginfo_t
* , ucontext_t
*)
588 ACE_DEBUG ((LM_DEBUG
,
589 ACE_TEXT ("(%P|%t) Stop_Handler::handle_signal - started.\n")));
590 if (! --this->counter_
)
592 ACE_DEBUG ((LM_INFO
, ACE_TEXT ("\n-- Stop_Handler::handle_signal --- ")
593 ACE_TEXT ("SIGNAL %d RECEIVED -----------.\n"),
595 return reactor ()->notify (this, ACE_Event_Handler::READ_MASK
);
597 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) Stop_Handler::handle_signal - ")
598 ACE_TEXT ("finished.\n")));
603 Stop_Handler::handle_input (ACE_HANDLE handle
)
605 ACE_UNUSED_ARG (handle
);
608 ACE_TEXT ("(%P|%t) Stop_Handler::handle_input - entered\n")));
610 for (size_t i
= 0; i
< HANDLERS_TO_STOP_TABLE_SIZE
; ++i
)
612 // remove from the reactor's tables all non-null entries
613 if (this->handlers_to_stop_
[i
])
615 // protect from deleted pointer
618 this->reactor ()->cancel_timer (this->handlers_to_stop_
[i
]);
619 this->reactor ()->remove_handler
620 (this->handlers_to_stop_
[i
],
621 ACE_Event_Handler::ALL_EVENTS_MASK
622 | ACE_Event_Handler::DONT_CALL
);
626 ACE_ERROR ((LM_ERROR
,
627 ACE_TEXT ("(%P|%t) Stop_Handler::handle_input - ")
628 ACE_TEXT ("EXCEPTION CATCHED. Most probably ")
629 ACE_TEXT ("handler's pointer has been deleted.\n")));
631 this->handlers_to_stop_
[i
] = 0;
635 this->reactor ()->remove_handler (this->registered_signals_
);
637 if (reactor ()->end_reactor_event_loop () == -1)
639 ACE_ERROR_RETURN ((LM_DEBUG
,
640 ACE_TEXT ("(%P|%t) Stop_Handler::handle_signal:%p\n"),
641 ACE_TEXT ("end_reactor_event_loop")),
646 ACE_TEXT ("(%P|%t) Stop_Handler::handle_input - completed.\n")));
651 Stop_Handler::handle_close (ACE_HANDLE
, ACE_Reactor_Mask m
)
654 ACE_TEXT ("(%P|%t) Stop_Handler::handle_close - entered.\n")));
655 if (m
== ACE_Event_Handler::SIGNAL_MASK
)
657 this->reactor ()->remove_handler (this,
658 ACE_Event_Handler::SIGNAL_MASK
|
659 ACE_Event_Handler::DONT_CALL
);
661 if (reactor ()->end_reactor_event_loop () == -1)
662 ACE_ERROR_RETURN ((LM_DEBUG
,
663 ACE_TEXT ("Stop_Handler::handle_close: %p\n"),
664 ACE_TEXT ("end_reactor_event_loop")),
670 Stop_Handler::handle_timeout (ACE_Time_Value
const &,
676 // Register handler with us for stopping.
678 Stop_Handler::register_handler (ACE_Event_Handler
*handler
)
681 ACE_ERROR_RETURN ((LM_ERROR
,
682 ACE_TEXT ("(%P|%t) Stop_Handler::register_handler - ")
683 ACE_TEXT ("error, handler is a null pointer.\n")),
689 (index
< HANDLERS_TO_STOP_TABLE_SIZE
&&
690 this->handlers_to_stop_
[index
]);
694 if (index
== HANDLERS_TO_STOP_TABLE_SIZE
)
696 ACE_ERROR_RETURN ((LM_ERROR
,
697 ACE_TEXT ("(%P|%t) Stop_Handler::register_handler ")
698 ACE_TEXT ("- error, no space in ")
699 ACE_TEXT ("handlers_to_stop_table.\nIncrease ")
700 ACE_TEXT ("HANDLERS_TO_STOP_TABLE_SIZE.\n")),
704 this->handlers_to_stop_
[index
] = handler
;
708 // Unregister handler, registered before with us for stopping.
710 Stop_Handler::unregister_handler (ACE_Event_Handler
*handler
)
713 ACE_ERROR_RETURN ((LM_ERROR
,
714 ACE_TEXT ("(%P|%t) Stop_Handler::unregister_handler - ")
715 ACE_TEXT ("error, handler is a null pointer.\n")),
721 (index
< HANDLERS_TO_STOP_TABLE_SIZE
&&
722 handler
!= this->handlers_to_stop_
[index
]);
727 if (index
== HANDLERS_TO_STOP_TABLE_SIZE
)
728 ACE_ERROR_RETURN ((LM_ERROR
,
729 ACE_TEXT ("(%P|%t) Stop_Handler::unregister_")
730 ACE_TEXT ("handler - error, the handler was not ")
731 ACE_TEXT ("found among registered handlers.\n")),
735 // null the entrance. Nulled entrances cannot be destroyed
736 this->handlers_to_stop_
[entrance
] = 0;
742 Repeats_Handler::Repeats_Handler ()
743 : check_handler_ (0),
749 Repeats_Handler::~Repeats_Handler ()
752 ACE_TEXT ("(%P|%t) Repeats_Handler::~Repeats_Handler.\n")));
756 Repeats_Handler::open (Echo_Handler
* check_handler
,
757 ACE_Reactor
* const reactor
,
758 unsigned int seconds_timer
)
761 ACE_ERROR_RETURN ((LM_ERROR
,
762 ACE_TEXT ("(%P|%t) Repeats_Handler::open - error: ")
763 ACE_TEXT ("NULL check_handler.\n")),
766 this->check_handler_
= check_handler
;
769 ACE_ERROR_RETURN ((LM_ERROR
,
770 ACE_TEXT ("(%P|%t) Stop_Handler::open - error: ")
771 ACE_TEXT ("NULL reactor.\n")),
774 this->reactor (reactor
);
775 this->seconds_timer_
= seconds_timer
;
777 if (this->reactor ()->schedule_timer (
781 ACE_Time_Value (this->seconds_timer_
)) == -1)
782 ACE_ERROR_RETURN ((LM_ERROR
,
783 ACE_TEXT ("(%P|%t) Repeats_Handler::open: %p\n"),
784 ACE_TEXT ("schedule_timer")),
790 Repeats_Handler::handle_close (ACE_HANDLE
, ACE_Reactor_Mask
)
794 ACE_TEXT ("(%P|%t) Repeats_Handler::handle_close - entered.\n")));
796 this->reactor ()->remove_handler (this,
797 ACE_Event_Handler::ALL_EVENTS_MASK
|
798 ACE_Event_Handler::DONT_CALL
);
802 static int one_button_test
= 0;
805 Repeats_Handler::handle_timeout (ACE_Time_Value
const &,
809 if (one_button_test
&& this->counter_
> 3)
811 ACE_OS::raise (SIGINT
);
813 if (this->check_handler_
)
815 return this->check_handler_
->dispatch_echo_checks (true);
821 // to create core on some UNIX platforms
822 #if defined (ACE_HAS_SIG_C_FUNC)
825 #endif /* #if defined (ACE_HAS_SIG_C_FUNC) */
827 #if ! defined (ACE_WIN32)
828 static void sigsegv_handler (int)
832 #endif /* #if ! defined (ACE_WIN32) */
834 #if defined (ACE_HAS_SIG_C_FUNC)
836 #endif /* #if defined (ACE_HAS_SIG_C_FUNC) */
838 #if defined (ACE_WIN32)
839 static BOOL WINAPI
CtrlHandler(DWORD fdwCtrlType
)
844 case CTRL_BREAK_EVENT
:
845 case CTRL_SHUTDOWN_EVENT
:
846 case CTRL_CLOSE_EVENT
:
847 case CTRL_LOGOFF_EVENT
:
848 ACE_OS::raise (SIGINT
);
851 // Pass other signals to the next handler.
856 #endif /* #if defined (ACE_WIN32) */
858 #define MAX_NUMBER_OF_PING_POINTS 16
860 static int number_of_ping_points
= 0;
861 static char ping_points_ips
[MAX_NUMBER_OF_PING_POINTS
][16];
862 static ACE_INET_Addr ping_points_addrs
[MAX_NUMBER_OF_PING_POINTS
];
863 static char local_ip_to_bind
[16];
865 static int wait_echo_reply_timer
= 500; // 500 ms to wait is the default
866 static int repeats_seconds_timer
= 60; // 60 seconds between repeats
869 is_ip_address_local (char const * const ip_to_bind
)
871 ACE_INET_Addr
*the_addr_array
= 0;
873 int rc
= ACE::get_ip_interfaces (how_many
, the_addr_array
);
876 ACE_ERROR_RETURN ((LM_ERROR
,
877 ACE_TEXT ("is_ip_address_local: %p\n"),
878 ACE_TEXT ("ACE::get_ip_interfaces")),
882 ACE_ERROR_RETURN ((LM_ERROR
,
883 ACE_TEXT ("is_ip_address_local: "),
884 ACE_TEXT ("No interfaces presently configured ")
885 ACE_TEXT ("in the kernel\n")),
888 // debugging messages
889 ACE_DEBUG ((LM_DEBUG
,
890 ACE_TEXT ("is_ip_address_local () - there are %d interfaces\n"),
893 for (size_t i
= 0; i
< how_many
; ++i
)
895 ACE_DEBUG ((LM_DEBUG
,
897 the_addr_array
[i
].get_host_addr ()));
900 for (size_t j
= 0; j
< how_many
; ++j
)
902 if (!ACE_OS::strcmp (the_addr_array
[j
].get_host_addr (), ip_to_bind
))
911 parse_args (int argc
, ACE_TCHAR
*argv
[])
913 ACE_OS::memset (ping_points_ips
, 0, sizeof ping_points_ips
);
914 ACE_OS::memset (local_ip_to_bind
, 0, sizeof local_ip_to_bind
);
916 if (argc
== 1) // one button test
919 repeats_seconds_timer
= 2;
920 number_of_ping_points
= 1;
922 ACE_OS::strncpy (ping_points_ips
[0],
924 sizeof ping_points_ips
[0]);
926 ping_points_addrs
[0].set ((u_short
) 0, ping_points_ips
[0]);
930 ACE_Get_Opt
get_opt (argc
, argv
, ACE_TEXT ("b:p:t:w:"));
932 ACE_INET_Addr b_temp_addr
;
933 ACE_TCHAR
*token
= 0;
934 while ((c
= get_opt ()) != EOF
)
938 case 'b': // ip-address of the interface to bind to
939 ACE_OS::strncpy (local_ip_to_bind
,
940 ACE_TEXT_ALWAYS_CHAR (get_opt
.optarg
),
941 sizeof local_ip_to_bind
);
943 if (!ACE_OS::strlen (local_ip_to_bind
) ||
944 b_temp_addr
.set ((u_short
)0, local_ip_to_bind
) != 0)
946 ACE_ERROR ((LM_ERROR
,
947 ACE_TEXT ("-b should be followed by a valid ")
948 ACE_TEXT ("IPv4 address.\n")));
952 if (is_ip_address_local (local_ip_to_bind
) == -1)
954 ACE_ERROR_RETURN ((LM_ERROR
,
955 ACE_TEXT ("the -b address (%s) ")
956 ACE_TEXT ("is not a local ")
957 ACE_TEXT ("address of your computer.\n")
958 ACE_TEXT ("\tPlease correct it.\n"),
964 case 'p': // ping-point (target) ip-addresses, separated by ":'"
966 // tokenizing the string
967 for (token
= ACE_OS::strtok (get_opt
.optarg
, ACE_TEXT (":"));
968 token
!= 0 && counter
< MAX_NUMBER_OF_PING_POINTS
;
969 token
= ACE_OS::strtok (0, ACE_TEXT (":")))
971 if (ping_points_addrs
[counter
].set ((u_short
)0, token
) != 0)
974 ACE_TEXT ("Error: the address \"%s\" is not ")
975 ACE_TEXT ("a valid IPv4 address.\n"),
978 ++number_of_ping_points
;
984 repeats_seconds_timer
= ACE_OS::atoi (get_opt
.optarg
);
988 wait_echo_reply_timer
= ACE_OS::atoi (get_opt
.optarg
);
992 // return print_usage (argc,argv);
997 if (!number_of_ping_points
)
999 ACE_ERROR_RETURN ((LM_ERROR
,
1000 ACE_TEXT ("Error: no valid IPv4 addresses ")
1001 ACE_TEXT ("were provided, using -p option.\n")),
1009 run_main (int argc
, ACE_TCHAR
*argv
[])
1011 ACE_START_TEST (ACE_TEXT ("Network_Adapters_Test"));
1013 #if defined (ACE_WIN32)
1014 SetConsoleCtrlHandler(&CtrlHandler
, TRUE
);
1015 #else /* #if defined (ACE_WIN32) */
1016 // Set a handler for SIGSEGV signal to call for abort.
1017 ACE_Sig_Action
sa1 ((ACE_SignalHandler
) sigsegv_handler
, SIGSEGV
);
1018 #endif /* #if defined (ACE_WIN32) */
1019 if (::parse_args (argc
, argv
) == -1)
1024 ACE_Reactor
* main_reactor
= 0;
1025 ACE_NEW_RETURN (main_reactor
, ACE_Reactor
, -1);
1027 (void) ACE_High_Res_Timer::global_scale_factor ();
1029 // Change the source of time in the reactor to the high-resolution
1030 // timer. Why does this test require such precision for a 1 second
1031 // timer is beyond me ... I think it is a cut&paste error.
1033 // The use of auto_ptr<> is optional, ACE uses dangerous memory
1034 // management idioms everywhere, I thought I could demonstrate how
1035 // to do it right in at least one test. Notice the lack of
1036 // ACE_NEW_RETURN, that monstrosity has no business in proper C++
1038 std::unique_ptr
<ACE_Timer_Heap_Variable_Time_Source
> tq(
1039 new ACE_Timer_Heap_Variable_Time_Source
);
1040 // ... notice how the policy is in the derived timer queue type.
1041 // The abstract timer queue does not have a time policy ...
1042 tq
->set_time_policy(&ACE_High_Res_Timer::gettimeofday_hr
);
1043 // ... and then the timer queue is replaced. Strangely, the reactor
1044 // does *not* copy the timers, it just deletes the existing timer
1046 main_reactor
->timer_queue(tq
.get());
1047 // ... the reactor does not assume ownership
1050 * Stop_Handler's is supposed to stop the activity of all
1051 * handlers by a SIGINT signal. We create and activate here an object of
1052 * Stop_Handler and pass an instance of reactor (main_reactor),
1053 * running demultiplexing event loop in the "main thread".
1055 Stop_Handler
* stop_handler
= 0;
1056 ACE_NEW_RETURN (stop_handler
, Stop_Handler (main_reactor
), -1);
1057 if (stop_handler
->open () == -1)
1059 ACE_ERROR ((LM_ERROR
,
1060 ACE_TEXT ("(%P|%t) %p\n"),
1061 ACE_TEXT ("main() - stop_handler->open")));
1065 ACE_TCHAR
*ping_status
= 0;
1066 ACE_NEW_RETURN (ping_status
, ACE_TCHAR
[number_of_ping_points
], -1);
1068 // wait_echo_reply_timer is in msec
1070 int milliseconds
= 0;
1071 seconds
= wait_echo_reply_timer
/ 1000;
1072 milliseconds
= wait_echo_reply_timer
% 1000;
1073 ACE_Time_Value
const wait_timer (seconds
, milliseconds
);
1075 Echo_Handler
*ping_handler
= 0;
1076 ACE_NEW_RETURN (ping_handler
, Echo_Handler
, -1);
1078 if (ACE_OS::strlen (local_ip_to_bind
))
1080 // We are willing to bind the raw-socket to a certain adapter,
1081 // probably because we are willing to check connectivity/etc
1082 // of the local adapter.
1083 ACE_INET_Addr local_adapter
;
1084 local_adapter
.set ((u_short
) 0, local_ip_to_bind
);
1085 if (ping_handler
->open (main_reactor
,
1088 number_of_ping_points
,
1090 2, // max_attempts_number
1091 local_adapter
) == -1)
1094 // If this process doesn't have privileges to open a raw socket, log
1095 // a warning instead of an error.
1096 if (errno
== EPERM
|| errno
== EACCES
)
1098 ACE_ERROR ((LM_WARNING
,
1099 ACE_TEXT ("(%P|%t) main() - ping_handler->open: ")
1100 ACE_TEXT ("insufficient privs to run this test\n")));
1104 ACE_ERROR ((LM_ERROR
,
1105 ACE_TEXT ("(%P|%t) %p\n"),
1106 ACE_TEXT ("main() - ping_handler->open")));
1109 delete ping_handler
;
1110 delete [] ping_status
;
1111 delete main_reactor
;
1112 delete stop_handler
;
1120 // Binding to a local adapter is not of our interest. We just
1121 // are willing to check all these remote IPs, to monitor, that
1123 if (ping_handler
->open (main_reactor
,
1126 number_of_ping_points
,
1128 2) == -1) // max_attempts_number
1131 if (errno
== EPERM
|| errno
== EACCES
)
1133 ACE_ERROR ((LM_WARNING
,
1134 ACE_TEXT ("(%P|%t) main() - ping_handler->open: ")
1135 ACE_TEXT ("insufficient privs to run this test\n")));
1139 ACE_ERROR ((LM_ERROR
,
1140 ACE_TEXT ("(%P|%t) %p\n"),
1141 ACE_TEXT ("main() - ping_handler->open")));
1144 delete ping_handler
;
1145 delete [] ping_status
;
1146 delete main_reactor
;
1147 delete stop_handler
;
1154 Repeats_Handler
*repeats_handler
= 0;
1155 ACE_NEW_RETURN (repeats_handler
, Repeats_Handler
, -1);
1156 if (repeats_handler
->open (ping_handler
,
1158 repeats_seconds_timer
) == -1)
1160 ACE_ERROR ((LM_ERROR
,
1161 ACE_TEXT ("(%P|%t) %p\n"),
1162 ACE_TEXT ("main() - repeats_handler->open")));
1164 delete repeats_handler
;
1165 delete ping_handler
;
1166 delete [] ping_status
;
1167 delete main_reactor
;
1168 delete stop_handler
;
1174 stop_handler
->register_handler (repeats_handler
);
1175 stop_handler
->register_handler (ping_handler
);
1177 // Demultiplexing event loop of the main_reactor.
1178 while (main_reactor
->reactor_event_loop_done () == 0)
1180 main_reactor
->run_reactor_event_loop ();
1183 ACE_DEBUG ((LM_INFO
,
1184 ACE_TEXT ("(%P|%t|%T) \"Network_Adapters_Test\" main() - ")
1185 ACE_TEXT ("out of reactor's loop.\n")));
1187 delete repeats_handler
;
1188 delete ping_handler
;
1189 delete [] ping_status
;
1190 delete main_reactor
;
1191 delete stop_handler
;
1200 run_main (int, ACE_TCHAR
*[])
1202 ACE_START_TEST (ACE_TEXT ("Network_Adapters_Test"));
1204 ACE_DEBUG ((LM_INFO
,
1205 ACE_TEXT ("(%P|%t|%T) \"Network_Adapters_Test\" main() - ")
1206 ACE_TEXT ("ICMP support not configured.\n")
1207 ACE_TEXT ("Define ACE_HAS_ICMP_SUPPORT = 1 in your config.h ")
1208 ACE_TEXT ("file to enable.\n")));
1215 #endif /* ACE_HAS_ICMP_SUPPORT == 1 */