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"
30 #include "ace/Auto_Ptr.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 (void)
95 delete_success_status_ (0),
96 max_attempts_num_ (0),
98 connect_to_remote_ (0)
102 Echo_Handler::~Echo_Handler (void)
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 (void)
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 (void) 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 (void)
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 (void)
549 ACE_DEBUG ((LM_INFO
, ACE_TEXT ("(%P|%t) Stop_Handler::~Stop_Handler.\n")));
553 Stop_Handler::open (void)
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
,
590 ACE_DEBUG ((LM_DEBUG
,
591 ACE_TEXT ("(%P|%t) Stop_Handler::handle_signal - started.\n")));
592 if (! --this->counter_
)
594 ACE_DEBUG ((LM_INFO
, ACE_TEXT ("\n-- Stop_Handler::handle_signal --- ")
595 ACE_TEXT ("SIGNAL %d RECEIVED -----------.\n"),
597 return reactor ()->notify (this, ACE_Event_Handler::READ_MASK
);
599 ACE_DEBUG ((LM_DEBUG
, ACE_TEXT ("(%P|%t) Stop_Handler::handle_signal - ")
600 ACE_TEXT ("finished.\n")));
605 Stop_Handler::handle_input (ACE_HANDLE handle
)
607 ACE_UNUSED_ARG (handle
);
610 ACE_TEXT ("(%P|%t) Stop_Handler::handle_input - entered\n")));
612 for (size_t i
= 0; i
< HANDLERS_TO_STOP_TABLE_SIZE
; ++i
)
614 // remove from the reactor's tables all non-null entries
615 if (this->handlers_to_stop_
[i
])
617 #if defined ACE_HAS_EXCEPTIONS
619 // protect from deleted pointer
622 #endif // ACE_HAS_EXCEPTIONS
624 this->reactor ()->cancel_timer (this->handlers_to_stop_
[i
]);
625 this->reactor ()->remove_handler
626 (this->handlers_to_stop_
[i
],
627 ACE_Event_Handler::ALL_EVENTS_MASK
628 | ACE_Event_Handler::DONT_CALL
);
629 #if defined ACE_HAS_EXCEPTIONS
633 ACE_ERROR ((LM_ERROR
,
634 ACE_TEXT ("(%P|%t) Stop_Handler::handle_input - ")
635 ACE_TEXT ("EXCEPTION CATCHED. Most probably ")
636 ACE_TEXT ("handler's pointer has been deleted.\n")));
638 #endif // ACE_HAS_EXCEPTIONS
639 this->handlers_to_stop_
[i
] = 0;
643 this->reactor ()->remove_handler (this->registered_signals_
);
645 if (reactor ()->end_reactor_event_loop () == -1)
647 ACE_ERROR_RETURN ((LM_DEBUG
,
648 ACE_TEXT ("(%P|%t) Stop_Handler::handle_signal:%p\n"),
649 ACE_TEXT ("end_reactor_event_loop")),
654 ACE_TEXT ("(%P|%t) Stop_Handler::handle_input - completed.\n")));
659 Stop_Handler::handle_close (ACE_HANDLE
, ACE_Reactor_Mask m
)
662 ACE_TEXT ("(%P|%t) Stop_Handler::handle_close - entered.\n")));
663 if (m
== ACE_Event_Handler::SIGNAL_MASK
)
665 this->reactor ()->remove_handler (this,
666 ACE_Event_Handler::SIGNAL_MASK
|
667 ACE_Event_Handler::DONT_CALL
);
669 if (reactor ()->end_reactor_event_loop () == -1)
670 ACE_ERROR_RETURN ((LM_DEBUG
,
671 ACE_TEXT ("Stop_Handler::handle_close: %p\n"),
672 ACE_TEXT ("end_reactor_event_loop")),
678 Stop_Handler::handle_timeout (ACE_Time_Value
const &,
684 // Register handler with us for stopping.
686 Stop_Handler::register_handler (ACE_Event_Handler
*handler
)
689 ACE_ERROR_RETURN ((LM_ERROR
,
690 ACE_TEXT ("(%P|%t) Stop_Handler::register_handler - ")
691 ACE_TEXT ("error, handler is a null pointer.\n")),
697 (index
< HANDLERS_TO_STOP_TABLE_SIZE
&&
698 this->handlers_to_stop_
[index
]);
702 if (index
== HANDLERS_TO_STOP_TABLE_SIZE
)
704 ACE_ERROR_RETURN ((LM_ERROR
,
705 ACE_TEXT ("(%P|%t) Stop_Handler::register_handler ")
706 ACE_TEXT ("- error, no space in ")
707 ACE_TEXT ("handlers_to_stop_table.\nIncrease ")
708 ACE_TEXT ("HANDLERS_TO_STOP_TABLE_SIZE.\n")),
712 this->handlers_to_stop_
[index
] = handler
;
716 // Unregister handler, registered before with us for stopping.
718 Stop_Handler::unregister_handler (ACE_Event_Handler
*handler
)
721 ACE_ERROR_RETURN ((LM_ERROR
,
722 ACE_TEXT ("(%P|%t) Stop_Handler::unregister_handler - ")
723 ACE_TEXT ("error, handler is a null pointer.\n")),
729 (index
< HANDLERS_TO_STOP_TABLE_SIZE
&&
730 handler
!= this->handlers_to_stop_
[index
]);
735 if (index
== HANDLERS_TO_STOP_TABLE_SIZE
)
736 ACE_ERROR_RETURN ((LM_ERROR
,
737 ACE_TEXT ("(%P|%t) Stop_Handler::unregister_")
738 ACE_TEXT ("handler - error, the handler was not ")
739 ACE_TEXT ("found among registered handlers.\n")),
743 // null the entrance. Nulled entrances cannot be destroyed
744 this->handlers_to_stop_
[entrance
] = 0;
750 Repeats_Handler::Repeats_Handler (void)
751 : check_handler_ (0),
757 Repeats_Handler::~Repeats_Handler (void)
760 ACE_TEXT ("(%P|%t) Repeats_Handler::~Repeats_Handler.\n")));
764 Repeats_Handler::open (Echo_Handler
* check_handler
,
765 ACE_Reactor
* const reactor
,
766 unsigned int seconds_timer
)
769 ACE_ERROR_RETURN ((LM_ERROR
,
770 ACE_TEXT ("(%P|%t) Repeats_Handler::open - error: ")
771 ACE_TEXT ("NULL check_handler.\n")),
774 this->check_handler_
= check_handler
;
777 ACE_ERROR_RETURN ((LM_ERROR
,
778 ACE_TEXT ("(%P|%t) Stop_Handler::open - error: ")
779 ACE_TEXT ("NULL reactor.\n")),
782 this->reactor (reactor
);
783 this->seconds_timer_
= seconds_timer
;
785 if (this->reactor ()->schedule_timer (
789 ACE_Time_Value (this->seconds_timer_
)) == -1)
790 ACE_ERROR_RETURN ((LM_ERROR
,
791 ACE_TEXT ("(%P|%t) Repeats_Handler::open: %p\n"),
792 ACE_TEXT ("schedule_timer")),
798 Repeats_Handler::handle_close (ACE_HANDLE
, ACE_Reactor_Mask
)
802 ACE_TEXT ("(%P|%t) Repeats_Handler::handle_close - entered.\n")));
804 this->reactor ()->remove_handler (this,
805 ACE_Event_Handler::ALL_EVENTS_MASK
|
806 ACE_Event_Handler::DONT_CALL
);
810 static int one_button_test
= 0;
813 Repeats_Handler::handle_timeout (ACE_Time_Value
const &,
817 if (one_button_test
&& this->counter_
> 3)
819 ACE_OS::raise (SIGINT
);
821 if (this->check_handler_
)
823 return this->check_handler_
->dispatch_echo_checks (true);
829 // to create core on some UNIX platforms
830 #if defined (ACE_HAS_SIG_C_FUNC)
833 #endif /* #if defined (ACE_HAS_SIG_C_FUNC) */
835 #if ! defined (ACE_WIN32)
836 static void sigsegv_handler (int)
840 #endif /* #if ! defined (ACE_WIN32) */
842 #if defined (ACE_HAS_SIG_C_FUNC)
844 #endif /* #if defined (ACE_HAS_SIG_C_FUNC) */
846 #if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
847 static BOOL WINAPI
CtrlHandler(DWORD fdwCtrlType
)
852 case CTRL_BREAK_EVENT
:
853 case CTRL_SHUTDOWN_EVENT
:
854 case CTRL_CLOSE_EVENT
:
855 case CTRL_LOGOFF_EVENT
:
856 ACE_OS::raise (SIGINT
);
859 // Pass other signals to the next handler.
864 #endif /* #if defined (ACE_WIN32) */
866 #define MAX_NUMBER_OF_PING_POINTS 16
868 static int number_of_ping_points
= 0;
869 static char ping_points_ips
[MAX_NUMBER_OF_PING_POINTS
][16];
870 static ACE_INET_Addr ping_points_addrs
[MAX_NUMBER_OF_PING_POINTS
];
871 static char local_ip_to_bind
[16];
873 static int wait_echo_reply_timer
= 500; // 500 ms to wait is the default
874 static int repeats_seconds_timer
= 60; // 60 seconds between repeats
877 is_ip_address_local (char const * const ip_to_bind
)
879 ACE_INET_Addr
*the_addr_array
= 0;
881 int rc
= ACE::get_ip_interfaces (how_many
, the_addr_array
);
884 ACE_ERROR_RETURN ((LM_ERROR
,
885 ACE_TEXT ("is_ip_address_local: %p\n"),
886 ACE_TEXT ("ACE::get_ip_interfaces")),
890 ACE_ERROR_RETURN ((LM_ERROR
,
891 ACE_TEXT ("is_ip_address_local: "),
892 ACE_TEXT ("No interfaces presently configured ")
893 ACE_TEXT ("in the kernel\n")),
896 // debugging messages
897 ACE_DEBUG ((LM_DEBUG
,
898 ACE_TEXT ("is_ip_address_local () - there are %d interfaces\n"),
901 for (size_t i
= 0; i
< how_many
; ++i
)
903 ACE_DEBUG ((LM_DEBUG
,
905 the_addr_array
[i
].get_host_addr ()));
908 for (size_t j
= 0; j
< how_many
; ++j
)
910 if (!ACE_OS::strcmp (the_addr_array
[j
].get_host_addr (), ip_to_bind
))
919 parse_args (int argc
, ACE_TCHAR
*argv
[])
921 ACE_OS::memset (ping_points_ips
, 0, sizeof ping_points_ips
);
922 ACE_OS::memset (local_ip_to_bind
, 0, sizeof local_ip_to_bind
);
924 if (argc
== 1) // one button test
927 repeats_seconds_timer
= 2;
928 number_of_ping_points
= 1;
930 ACE_OS::strncpy (ping_points_ips
[0],
932 sizeof ping_points_ips
[0]);
934 ping_points_addrs
[0].set ((u_short
) 0, ping_points_ips
[0]);
938 ACE_Get_Opt
get_opt (argc
, argv
, ACE_TEXT ("b:p:t:w:"));
940 ACE_INET_Addr b_temp_addr
;
941 ACE_TCHAR
*token
= 0;
942 while ((c
= get_opt ()) != EOF
)
946 case 'b': // ip-address of the interface to bind to
947 ACE_OS::strncpy (local_ip_to_bind
,
948 ACE_TEXT_ALWAYS_CHAR (get_opt
.optarg
),
949 sizeof local_ip_to_bind
);
951 if (!ACE_OS::strlen (local_ip_to_bind
) ||
952 b_temp_addr
.set ((u_short
)0, local_ip_to_bind
) != 0)
954 ACE_ERROR ((LM_ERROR
,
955 ACE_TEXT ("-b should be followed by a valid ")
956 ACE_TEXT ("IPv4 address.\n")));
960 if (is_ip_address_local (local_ip_to_bind
) == -1)
962 ACE_ERROR_RETURN ((LM_ERROR
,
963 ACE_TEXT ("the -b address (%s) ")
964 ACE_TEXT ("is not a local ")
965 ACE_TEXT ("address of your computer.\n")
966 ACE_TEXT ("\tPlease correct it.\n"),
972 case 'p': // ping-point (target) ip-addresses, separated by ":'"
974 // tokenizing the string
975 for (token
= ACE_OS::strtok (get_opt
.optarg
, ACE_TEXT (":"));
976 token
!= 0 && counter
< MAX_NUMBER_OF_PING_POINTS
;
977 token
= ACE_OS::strtok (0, ACE_TEXT (":")))
979 if (ping_points_addrs
[counter
].set ((u_short
)0, token
) != 0)
982 ACE_TEXT ("Error: the address \"%s\" is not ")
983 ACE_TEXT ("a valid IPv4 address.\n"),
986 ++number_of_ping_points
;
992 repeats_seconds_timer
= ACE_OS::atoi (get_opt
.optarg
);
996 wait_echo_reply_timer
= ACE_OS::atoi (get_opt
.optarg
);
1000 // return print_usage (argc,argv);
1006 if (!number_of_ping_points
)
1008 ACE_ERROR_RETURN ((LM_ERROR
,
1009 ACE_TEXT ("Error: no valid IPv4 addresses ")
1010 ACE_TEXT ("were provided, using -p option.\n")),
1018 run_main (int argc
, ACE_TCHAR
*argv
[])
1020 ACE_START_TEST (ACE_TEXT ("Network_Adapters_Test"));
1022 #if defined (ACE_WIN32)
1023 #if !defined (ACE_HAS_WINCE)
1024 SetConsoleCtrlHandler(&CtrlHandler
, TRUE
);
1026 #else /* #if defined (ACE_WIN32) */
1027 // Set a handler for SIGSEGV signal to call for abort.
1028 ACE_Sig_Action
sa1 ((ACE_SignalHandler
) sigsegv_handler
, SIGSEGV
);
1029 #endif /* #if defined (ACE_WIN32) */
1030 if (::parse_args (argc
, argv
) == -1)
1035 ACE_Reactor
* main_reactor
= 0;
1036 ACE_NEW_RETURN (main_reactor
, ACE_Reactor
, -1);
1038 (void) ACE_High_Res_Timer::global_scale_factor ();
1040 // Change the source of time in the reactor to the high-resolution
1041 // timer. Why does this test require such precision for a 1 second
1042 // timer is beyond me ... I think it is a cut&paste error.
1044 // The use of auto_ptr<> is optional, ACE uses dangerous memory
1045 // management idioms everywhere, I thought I could demonstrate how
1046 // to do it right in at least one test. Notice the lack of
1047 // ACE_NEW_RETURN, that monstrosity has no business in proper C++
1049 auto_ptr
<ACE_Timer_Heap_Variable_Time_Source
> tq(
1050 new ACE_Timer_Heap_Variable_Time_Source
);
1051 // ... notice how the policy is in the derived timer queue type.
1052 // The abstract timer queue does not have a time policy ...
1053 tq
->set_time_policy(&ACE_High_Res_Timer::gettimeofday_hr
);
1054 // ... and then the timer queue is replaced. Strangely, the reactor
1055 // does *not* copy the timers, it just deletes the existing timer
1057 main_reactor
->timer_queue(tq
.get());
1058 // ... the reactor does not assume ownership
1061 * Stop_Handler's is supposed to stop the activity of all
1062 * handlers by a SIGINT signal. We create and activate here an object of
1063 * Stop_Handler and pass an instance of reactor (main_reactor),
1064 * running demultiplexing event loop in the "main thread".
1066 Stop_Handler
* stop_handler
= 0;
1067 ACE_NEW_RETURN (stop_handler
, Stop_Handler (main_reactor
), -1);
1068 if (stop_handler
->open () == -1)
1070 ACE_ERROR ((LM_ERROR
,
1071 ACE_TEXT ("(%P|%t) %p\n"),
1072 ACE_TEXT ("main() - stop_handler->open")));
1076 ACE_TCHAR
*ping_status
= 0;
1077 ACE_NEW_RETURN (ping_status
, ACE_TCHAR
[number_of_ping_points
], -1);
1079 // wait_echo_reply_timer is in msec
1081 int milliseconds
= 0;
1082 seconds
= wait_echo_reply_timer
/ 1000;
1083 milliseconds
= wait_echo_reply_timer
% 1000;
1084 ACE_Time_Value
const wait_timer (seconds
, milliseconds
);
1086 Echo_Handler
*ping_handler
= 0;
1087 ACE_NEW_RETURN (ping_handler
, Echo_Handler
, -1);
1089 if (ACE_OS::strlen (local_ip_to_bind
))
1091 // We are willing to bind the raw-socket to a certain adapter,
1092 // probably because we are willing to check connectivity/etc
1093 // of the local adapter.
1094 ACE_INET_Addr local_adapter
;
1095 local_adapter
.set ((u_short
) 0, local_ip_to_bind
);
1096 if (ping_handler
->open (main_reactor
,
1099 number_of_ping_points
,
1101 2, // max_attempts_number
1102 local_adapter
) == -1)
1105 // If this process doesn't have privileges to open a raw socket, log
1106 // a warning instead of an error.
1107 if (errno
== EPERM
|| errno
== EACCES
)
1109 ACE_ERROR ((LM_WARNING
,
1110 ACE_TEXT ("(%P|%t) main() - ping_handler->open: ")
1111 ACE_TEXT ("insufficient privs to run this test\n")));
1115 ACE_ERROR ((LM_ERROR
,
1116 ACE_TEXT ("(%P|%t) %p\n"),
1117 ACE_TEXT ("main() - ping_handler->open")));
1120 delete ping_handler
;
1121 delete [] ping_status
;
1122 delete main_reactor
;
1123 delete stop_handler
;
1131 // Binding to a local adapter is not of our interest. We just
1132 // are willing to check all these remote IPs, to monitor, that
1134 if (ping_handler
->open (main_reactor
,
1137 number_of_ping_points
,
1139 2) == -1) // max_attempts_number
1142 if (errno
== EPERM
|| errno
== EACCES
)
1144 ACE_ERROR ((LM_WARNING
,
1145 ACE_TEXT ("(%P|%t) main() - ping_handler->open: ")
1146 ACE_TEXT ("insufficient privs to run this test\n")));
1150 ACE_ERROR ((LM_ERROR
,
1151 ACE_TEXT ("(%P|%t) %p\n"),
1152 ACE_TEXT ("main() - ping_handler->open")));
1155 delete ping_handler
;
1156 delete [] ping_status
;
1157 delete main_reactor
;
1158 delete stop_handler
;
1165 Repeats_Handler
*repeats_handler
= 0;
1166 ACE_NEW_RETURN (repeats_handler
, Repeats_Handler
, -1);
1167 if (repeats_handler
->open (ping_handler
,
1169 repeats_seconds_timer
) == -1)
1171 ACE_ERROR ((LM_ERROR
,
1172 ACE_TEXT ("(%P|%t) %p\n"),
1173 ACE_TEXT ("main() - repeats_handler->open")));
1175 delete repeats_handler
;
1176 delete ping_handler
;
1177 delete [] ping_status
;
1178 delete main_reactor
;
1179 delete stop_handler
;
1185 stop_handler
->register_handler (repeats_handler
);
1186 stop_handler
->register_handler (ping_handler
);
1188 // Demultiplexing event loop of the main_reactor.
1189 while (main_reactor
->reactor_event_loop_done () == 0)
1191 main_reactor
->run_reactor_event_loop ();
1194 ACE_DEBUG ((LM_INFO
,
1195 ACE_TEXT ("(%P|%t|%T) \"Network_Adapters_Test\" main() - ")
1196 ACE_TEXT ("out of reactor's loop.\n")));
1198 delete repeats_handler
;
1199 delete ping_handler
;
1200 delete [] ping_status
;
1201 delete main_reactor
;
1202 delete stop_handler
;
1211 run_main (int, ACE_TCHAR
*[])
1213 ACE_START_TEST (ACE_TEXT ("Network_Adapters_Test"));
1215 ACE_DEBUG ((LM_INFO
,
1216 ACE_TEXT ("(%P|%t|%T) \"Network_Adapters_Test\" main() - ")
1217 ACE_TEXT ("ICMP support not configured.\n")
1218 ACE_TEXT ("Define ACE_HAS_ICMP_SUPPORT = 1 in your config.h ")
1219 ACE_TEXT ("file to enable.\n")));
1226 #endif /* ACE_HAS_ICMP_SUPPORT == 1 */